# ruby encoding: utf-8

require 'securerandom'

class Rollen::RolleController < ApplicationController
  include ApplicationHelper
  include StationHelper

  helper_method :sort_column, :sort_direction

  def check_ability!
    return if [:edit_password, :update_password, :cors].include? action_name.to_sym
    if action_name.to_sym == :index
      unless current_user.hat_berechtigung?(Rollen::Berechtigung::Verwaltung_Zugangsverwaltung_ansehen)
        raise CanCan::AccessDenied.new
      end
      return
    end
    unless current_user.hat_berechtigung?(Rollen::Berechtigung::Verwaltung_Zugangsverwaltung_bearbeiten)
      raise CanCan::AccessDenied.new
    end
  end

  def index
    @station = last_selected_station

    rollen = Rollen::Rolle.all.to_a
    berechtigungen = Rollen::Berechtigung.order('name').to_a

    messstellen = StammdatenContext::GaugingStation.order(messtellen_nr: :asc)
    messstellen = messstellen.sort_by {|s| s.active_till.nil? ? 0 : 1}
    betreiber = StammdatenContext::Operator.all
    eigentuemer = StammdatenSLContext::Eigentuemer.all
    messnetze = StammdatenSLContext::Messnetz.select(:messnetz_nr, :messnetz).order(:messnetz).as_json

    render locals: {
      tools: Rollen::AutoRollen::TOOLS,
      gruppen: Rollen::AutoRollen::GRUPPEN,
      aktionen: Rollen::AutoRollen::AKTIONEN,
      messstellen: messstellen,
      betreiber: betreiber,
      eigentuemer: eigentuemer,
      messnetze: messnetze,
      rollen: rollen,
      rollen_hash: Hash[rollen.map { |it| [it.key, it] }],
      berechtigungen: berechtigungen,
      berechtigungen_hash: Hash[berechtigungen.map { |it| [it.key, it] }],
    }
  end

  def new
    @station = last_selected_station
    @rolle = Rollen::Rolle.new
    @back_path = rollen_rolle_index_path

    rollen = Rollen::Rolle.all.to_a
    berechtigungen = Rollen::Berechtigung.order('name').to_a

    messstellen = StammdatenContext::GaugingStation.order(messtellen_nr: :asc)
    messstellen = messstellen.sort_by {|s| s.active_till.nil? ? 0 : 1}
    betreiber = StammdatenContext::Operator.all
    eigentuemer = StammdatenSLContext::Eigentuemer.all
    messnetze = StammdatenSLContext::Messnetz.select(:messnetz_nr, :messnetz).order(:messnetz).as_json

    render locals: {
      tools: Rollen::AutoRollen::TOOLS,
      gruppen: Rollen::AutoRollen::GRUPPEN,
      aktionen: Rollen::AutoRollen::AKTIONEN,
      messstellen: messstellen,
      betreiber: betreiber,
      eigentuemer: eigentuemer,
      messnetze: messnetze,
      rollen: rollen,
      rollen_hash: Hash[rollen.map { |it| [it.key, it] }],
      berechtigungen: berechtigungen,
      berechtigungen_hash: Hash[berechtigungen.map { |it| [it.key, it] }],
    }
  end

  def create
    @station = last_selected_station
    @back_path = rollen_rolle_index_path
    @rolle = Rollen::Rolle.new
    @rolle.name = permitted_params[:name]
    @rolle.key = SecureRandom.uuid

    if @rolle.save
      flash.now[:notice] = t('notice.update')
    else
      flash.now[:alert] = t('alert.update')
      render action: 'new'
      return
    end

    Rollen::RolleTeilrolle.where(rolle_key: @rolle.key).each do |it|
      it.destroy
    end
    Rollen::RolleBerechtigung.where(rolle_key: @rolle.key).each do |it|
      it.destroy
    end

    teilrollen_keys = []
    teilrollen_keys += permitted_params[:teilrollen_allgemein].split(',')
    teilrollen_keys.each do |key|
      Rollen::RolleTeilrolle.new(rolle_key: @rolle.key, teilrolle_key: key).save
    end
    berechtigungen_keys = []
    berechtigungen_keys += permitted_params[:berechtigungen_allgemein].split(',')
    berechtigungen_keys.each do |key|
      Rollen::RolleBerechtigung.new(rolle_key: @rolle.key, berechtigung_key: key).save
    end

    BerechtigungsCache.instance.clear

    redirect_to rollen_rolle_index_path
  end

  def edit
    @station = last_selected_station
    @rolle = Rollen::Rolle.find(params[:id])
    @back_path = rollen_rolle_index_path

    rollen = Rollen::Rolle.all.to_a
    berechtigungen = Rollen::Berechtigung.order('name').to_a

    messstellen = StammdatenContext::GaugingStation.order(messtellen_nr: :asc)
    messstellen = messstellen.sort_by {|s| s.active_till.nil? ? 0 : 1}
    betreiber = StammdatenContext::Operator.all
    eigentuemer = StammdatenSLContext::Eigentuemer.all
    messnetze = StammdatenSLContext::Messnetz.select(:messnetz_nr, :messnetz).order(:messnetz).as_json

    render locals: {
      tools: Rollen::AutoRollen::TOOLS,
      gruppen: Rollen::AutoRollen::GRUPPEN,
      aktionen: Rollen::AutoRollen::AKTIONEN,
      messstellen: messstellen,
      betreiber: betreiber,
      eigentuemer: eigentuemer,
      messnetze: messnetze,
      rollen: rollen,
      rollen_hash: Hash[rollen.map { |it| [it.key, it] }],
      berechtigungen: berechtigungen,
      berechtigungen_hash: Hash[berechtigungen.map { |it| [it.key, it] }],
    }
  end

  def update
    @station = last_selected_station
    @back_path = rollen_rolle_index_path
    @rolle = Rollen::Rolle.find(params[:id])
    @rolle.name = permitted_params[:name]
    if @rolle.save
      flash[:notice] = t('notice.update')
    else
      flash.now[:alert] = t('alert.update')
      render action: 'edit'
      return
    end

    Rollen::RolleTeilrolle.where(rolle_key: @rolle.key).each do |it|
      it.destroy
    end
    Rollen::RolleBerechtigung.where(rolle_key: @rolle.key).each do |it|
      it.destroy
    end

    teilrollen_keys = []
    teilrollen_keys += permitted_params[:teilrollen_allgemein].split(',')
    teilrollen_keys.each do |key|
      test = Rollen::RolleTeilrolle.new
      test.rolle_key = @rolle.key
      test.teilrolle_key = key
      test.save
    end
    berechtigungen_keys = []
    berechtigungen_keys += permitted_params[:berechtigungen_allgemein].split(',')
    berechtigungen_keys.each do |key|
      Rollen::RolleBerechtigung.new(rolle_key: @rolle.key, berechtigung_key: key).save
    end

    BerechtigungsCache.instance.clear

    redirect_to rollen_rolle_index_path
  end

  def destroy
    @station = last_selected_station
    @rolle = Rollen::Rolle.find(params[:id])

    rolle_teilrollen  = Rollen::RolleTeilrolle.where(teilrolle_key: @rolle.key)
    rolle_teilrollen.each do |it|
      it.destroy
    end

    if @rolle.destroy
      flash[:notice] = t('notice.delete')
    else
      flash.now[:alert] = t('alert.delete')
    end

    BerechtigungsCache.instance.clear

    redirect_to rollen_rolle_index_path
  end

  def permitted_params
    params[:rolle].permit!
  end

  private

  def self.erzeuge_automatische_rollen_und_berechtigungen
    tools = Rollen::AutoRollen::TOOLS
    aktionen = Rollen::AutoRollen::AKTIONEN
    messstellen = StammdatenContext::GaugingStation.order(messtellen_nr: :asc)
    messstellen = messstellen.sort_by {|s| s.active_till.nil? ? 0 : 1}
    betreiber = StammdatenContext::Operator.all
    eigentuemer = StammdatenSLContext::Eigentuemer.all
    messnetze = StammdatenSLContext::Messnetz.select(:messnetz_nr, :messnetz).order(:messnetz).as_json

    berechtigungen = []
    rollen = []

    tools.each do |tool|
      messstellen.each_with_index do |messstelle, index|
        aktionen.each do |aktion|
          if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
            next
          end
          name = "#{tool[:name]} - Pegel #{messstelle.to_s}: #{aktion[:name]}"
          berechtigung = Rollen::Berechtigung.new(
            key: "auto-berechtigung-tool:#{tool[:key]}-pegel:#{messstelle.id}-aktion:#{aktion[:key]}",
            name: name)
          berechtigungen << berechtigung
          rolle = Rollen::Rolle.new(
            key: "auto-rolle-tool:#{tool[:key]}-pegel:#{messstelle.id}-aktion:#{aktion[:key]}",
            name: name, pos: index, suspended: messstelle.suspended?)
          rollen << rolle
        end
      end
    end

    tools.each do |tool|
      betreiber.each do |ein_betreiber|
        aktionen.each do |aktion|
          if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
            next
          end
          rollen << Rollen::Rolle.new(
            key: "auto-rolle-tool:#{tool[:key]}-betreiber:#{ein_betreiber.id}-aktion:#{aktion[:key]}",
            name: "#{tool[:name]} - Betreiber #{ein_betreiber.name}: #{aktion[:name]}",
            suspended: false)
        end
      end
      eigentuemer.each do |ein_eigentuemer|
        aktionen.each do |aktion|
          if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
            next
          end
          rollen << Rollen::Rolle.new(
            key: "auto-rolle-tool:#{tool[:key]}-eigentuemer:#{ein_eigentuemer.id}-aktion:#{aktion[:key]}",
            name: "#{tool[:name]} - Eigentümer #{ein_eigentuemer.name}: #{aktion[:name]}",
            suspended: false)
        end
      end
      messnetze.each do |ein_messnetz|
        aktionen.each do |aktion|
          if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
            next
          end
          rollen << Rollen::Rolle.new(
            key: "auto-rolle-tool:#{tool[:key]}-messnetz:#{ein_messnetz['messnetz_nr']}-aktion:#{aktion[:key]}",
            name: "#{tool[:name]} - Messnetz #{ein_messnetz['messnetz']}: #{aktion[:name]}",
            suspended: false)
        end
      end
    end

    alle_betreiber = 'Betreiber (Alle)'
    tools.each do |tool|
      aktionen.each do |aktion|
        if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
          next
        end
        rollen << Rollen::Rolle.new(
          key: "auto-rolle-tool:#{tool[:key]}-betreiber:alle-aktion:#{aktion[:key]}",
          name: "#{tool[:name]} - #{alle_betreiber}: #{aktion[:name]}",
          suspended: false)
      end
    end

    alle_messnetze = 'Messnetze (Alle)'
    tools.each do |tool|
      aktionen.each do |aktion|
        if aktion[:key] == 'bearbeiten' && tool[:key] == 'datenausgabe'
          next
        end
        rollen << Rollen::Rolle.new(
          key: "auto-rolle-tool:#{tool[:key]}-messnetz:alle-aktion:#{aktion[:key]}",
          name: "#{tool[:name]} - #{alle_messnetze}: #{aktion[:name]}",
          suspended: false)
      end
    end

    alle_tools = tools.find { |it| it[:key] == 'alle' }[:name]
    aktionen.each do |aktion|
      rollen << Rollen::Rolle.new(
        key: "auto-rolle-tool:alle-betreiber:alle-aktion:#{aktion[:key]}",
        name: "#{alle_tools} - #{alle_betreiber}: #{aktion[:name]}",
        suspended: false)
      rollen << Rollen::Rolle.new(
        key: "auto-rolle-tool:alle-messnetz:alle-aktion:#{aktion[:key]}",
        name: "#{alle_tools} - #{alle_messnetze}: #{aktion[:name]}",
        suspended: false)
    end

    betreiber.each do |ein_betreiber|
      aktionen.each do |aktion|
        rollen << Rollen::Rolle.new(
          key: "auto-rolle-tool:alle-betreiber:#{ein_betreiber.id}-aktion:#{aktion[:key]}",
          name: "#{alle_tools} - Betreiber #{ein_betreiber.name}: #{aktion[:name]}",
          suspended: false)
      end
    end
    eigentuemer.each do |ein_eigentuemer|
      aktionen.each do |aktion|
        rollen << Rollen::Rolle.new(
          key: "auto-rolle-tool:alle-eigentuemer:#{ein_eigentuemer.id}-aktion:#{aktion[:key]}",
          name: "#{alle_tools} - Eigentümer #{ein_eigentuemer.name}: #{aktion[:name]}",
          suspended: false)
      end
    end
    messnetze.each do |ein_messnetz|
      aktionen.each do |aktion|
        rollen << Rollen::Rolle.new(
          key: "auto-rolle-tool:alle-messnetz:#{ein_messnetz['messnetz_nr']}-aktion:#{aktion[:key]}",
          name: "#{alle_tools} - Messnetz #{ein_messnetz['messnetz']}: #{aktion[:name]}",
          suspended: false)
      end
    end

    alle_aktionen = 'Bearbeiten'
    rollen << Rollen::Rolle.new(
      key: "auto-rolle-tool:alle-betreiber:alle-aktion:alle",
      name: "#{alle_tools} - #{alle_betreiber}: #{alle_aktionen}",
      suspended: false
    )

    {berechtigungen: berechtigungen, rollen: rollen}
  end

  @@automatische_rollen_und_berechtigungen = self.erzeuge_automatische_rollen_und_berechtigungen

  def automatische_rollen_und_berechtigungen
    @@automatische_rollen_und_berechtigungen
  end

end