#encoding: utf-8
module DataController
  #BERICHTSZEITRAUM = "DE2011" #bitte hier jeden neuen Berichtszeitraum ändern!!!!!!!!!!!!!!!
  STANDARDLISTENLAENGE = 20 #used by view and generica to limit the amount of records returned by query

  include ApplicationHelper
  include ReportConcerns

  def index
    @gen = gen
    nur_aktuell = " and #{@datensatz}.rep_code = '#{ReportingPeriod.get_current.key_report}'"

    @where = nil #sagt dem exporter dass er den kompletten Datenbestand für diesen Datensatz für den aktuellen Berichtszeitraum verwenden soll
    @user = theUser(session)
    if params['amount'].to_i > 0
      @user.update_attributes(:rows_per_page => params['amount'])
    end
    @offset = params['offset']
    @data, @order = @gen.all(nur_aktuell, [], nil, @user.rows_per_page, params['offset'] || 0)
    render :template => 'layouts/list'
  end

  def new
    @gen = gen
    @data = Generica::Record.new({}, @gen, nil)
    render :template => 'layouts/new'
  end

  def edit
    @gen = gen
    @data = @gen.find_for_edit(params[:id])
    @prevReport = @gen.get_prev_report(params[:id])
    @nextReport = @gen.get_next_report(params[:id])
    if self.class::NAME == 'Agglomeration' || self.class::NAME == 'Einleitstelle' || self.class::NAME == 'Anlage'
      @map_urls = @gen.get_map_urls(params[:id])
    else
      @map_urls = nil
    end
    render :template => 'layouts/edit'
  end

  def create
    @gen = self.gen
    @data = @gen.insert(params)
    if @data.id.nil?
      render :template => 'layouts/new'
    else
      flash[:notice] = @data.successes.join("<br> \n").html_safe
      redirect_to :action => :edit, :id => @data.id
    end
  end

  def update
    @gen = self.gen
    @data = @gen.update(params)
    if @data.errors.empty?
      flash[:notice] = "Änderungen erfolgreich Übernommen"
      redirect_to :action => :edit, :id => @data.id
    else
      flash[:error] = "Änderungen konnten <b>nicht</b> übernommen werden"
      render :template => 'layouts/edit'
    end
  end

  def delete
    @gen = self.gen
    result = @gen.delete(params[:id]) # result[0] is true if successfull, result[1] stores messages
    text = ''
    if result[0] == true
      text << '<span style="color:green"> Der Eintrag wurde erfolgreich gelöscht.'
    else
      text << '<span style="color:red"> Der Eintrag konnte nicht gelöscht werden.'
    end
    result[1].each {|msg| text << '<br />' + msg}
    text << '</span>'
    flash[:notice] = text.html_safe
    redirect_to :action => :index, :offset => params[:offset]
  end

  def limited_list_update
    col_name = params[:col_name]
    human_name = params[:human_name]
    foreign_table = params[:foreign_table]
    federal_state_id = params[:federal_state_id]
    value = params[:value]
    rep_code = params[:rep_code]
    show_all = params[:show_all] == 'true'

    render :text => limited_list(col_name, human_name, foreign_table, federal_state_id, show_all, value, nil, rep_code)
  end

  def limited_list_json
    foreign_table = params[:foreign_table]
    federal_state_id = params[:federal_state_id]
    filter_text = params[:filter_text] || ''
    show_all = params[:show_all] == 'true'
    offset = params[:offset] || '0'
    rep_code = params[:rep_code]
    render :partial => 'layouts/filter_table', :locals => {:options => limited_list_options(foreign_table, federal_state_id, show_all, filter_text, offset, rep_code)}
  end

  def limited_list(col_name = nil, human_name = nil, foreign_table = nil, federal_state_id = nil, show_all = false, value = nil, disabled = false, rep_code = nil)
    if disabled
      # logger.info "\nValue ist: #{value}"
      text = limited_list_options(foreign_table, federal_state_id, show_all, filter_text = nil, offset = '0', rep_code, col_name, value).detect {|o| o[3] == value}
      # logger.info "\n\nTEXT: #{text}\n\n"
      return render_to_string(:partial => 'layouts/ref_ten_field_locked', :locals => {
          :col_name => col_name,
          :text => (text[0] rescue '')
      }).html_safe
    end

    return render_to_string(:partial => 'layouts/ref_ten_field', :locals => {
        :col_name => col_name,
        :human_name => human_name,
        :foreign_table => foreign_table,
        :federal_state_id => federal_state_id,
        :show_all => show_all ? 'true' : 'false',
        :value => value ? value.to_i : nil,
        :rep_code => rep_code,
        :options => limited_list_options(foreign_table, federal_state_id, show_all, filter_text = nil, offset = '0', rep_code, col_name, value)
    }).html_safe
  end

  def limited_list_options(foreign_table, federal_state_id, show_all, filter_text = nil, offset = '0', rep_code = nil, column = nil, value = nil)
    tables = [
        {:table => 'l_region_code', :key => 'key', :text => 'description'},
        {:table => 'l_water_body_code', :key => 'key', :text => 'description'},
        {:table => 'l_groundwater_body', :key => 'key', :text => 'description'},
        {:table => 'plants', :key => 'pl_key', :text => 'pl_name'},
    ]
    table = tables.detect {|t| t[:table] == foreign_table}
    return [] if table.nil?
    table[:key] ||= 'key'
    table[:text] ||= 'description'
    sql = "SELECT coalesce(ft.#{table[:key]} || ' - ' || ft.#{table[:text]}) as title,
                  ft.#{table[:key]},
                  ft.#{table[:text]},
                  ft.id
          FROM #{table[:table]} ft"


    #get report time data
    date_from, date_to = getReportTimeFrame(rep_code)

    case foreign_table
      when 'plants'
        sql << " JOIN model.reporting_periods rp ON ft.date_to = rp.date_to AND rp.state = 1" if foreign_table == 'plants'
        sql << " WHERE true"
      when 'l_water_body_code', 'l_groundwater_body'
        sql << " WHERE #{date_from} >= ft.date_from AND #{date_to} <= ft.date_to"
      when 'l_region_code'
        sql << " WHERE (ft.date_from IS NULL OR #{date_from} >= ft.date_from)"
        sql << " AND"
        sql << " (ft.date_to IS NULL OR #{date_to} <= ft.date_to)"
      else
        sql << " WHERE true"
    end
    states = []
    unless show_all
      #Diese Informationen dürfen Nutzer aus allen Bundesländern abfragen, weil manchmal ein Eintrag aus einem benachbarten Bundesland
      #eingetragen werden muss. federal_state_id darf also als Parameter übergeben werden, die session[:user]-Abfrage ist eher für neue Einträge.
      if federal_state_id
        states << federal_state_id
      else
        states = theUser(session).get_states_for_write
      end
      states << 17 if foreign_table == 'l_region_code'
      if !column.nil? and !value.nil?
        sql << " AND (ft.federal_state_id IN (#{states.collect {|v| '?'}.join(', ')}) OR ft.id = #{value})"
      else
        sql << " AND ft.federal_state_id IN (#{states.collect {|v| '?'}.join(', ')})"
      end
    end
    sql << " AND (ft.#{table[:key]} ILIKE ? OR ft.#{table[:text]} ILIKE ?)"
    sql << " ORDER BY ft.#{table[:key]}, federal_state_id"
    txt = "%#{like_sanitize(filter_text)}%"
    # logger.info "#{sql}"
    # logger.info "#{states}"
    # logger.info "#{txt}"

    result = ActiveRecord::Base.query_sql(sql, *states, txt, txt).to_a.insert(0, ["", ""])
    # logger.info "RESULT: #{result}\n\n\n"
    #
    return result
  end

  def add_successor
    logger.info "+++++++++++++++++++ ADD SUCCESSOR +++++++++++++++++++"


    @gen = gen
    try, error_msg = @gen.insert_predecessor(params[:pre_id], params[:succ_id])
    if try
      flash[:successor_notice] = 'Der Vorgänger wurde erfolgreich zugewiesen.'
    else
      if error_msg
        flash[:successor_error] = error_msg.html_safe
      else
        flash[:successor_error] = 'Der Vorgänger konnte nicht zugeordnet werden.'
      end
    end
    render :text => successor_select_with_add(params[:succ_id])
  end

  def delete_successor
    @gen = gen
    try, error_msg = @gen.delete_predecessor(params[:pre_id], params[:succ_id])
    if try
      flash[:successor_notice] = 'Die Zuordnung des Vorgängers wurde erfolgreich aufgehoben.'
    else
      if error_msg
        flash[:successor_error] = error_msg.html_safe
      else
        flash[:successor_error] = 'Die Zuordnung des Vorgängers konnte nicht aufgehoben werden.'
      end
    end
    render :text => successor_select_with_add(params[:succ_id])
  end

  def hide_successor_fields
    logger.info "+++++++++++++++++++ HIDE SUCCESSOR FIELDS +++++++++++++++++++"
    render :text => successor_select_with_add(params[:id])
  end

  def successor_select_with_add(id)
    return successor_select(id) +
        render_to_string(:partial => 'layouts/successor_add_btn', :locals => {:id => id}).html_safe
  end

  def show_successor_fields
    show_all = params[:show_all] == 'true'
    render(:partial => 'layouts/successor_field', :locals => {:successor_possibs => get_successor_possibs, :id => params[:id], :show_all => show_all ? 'true' : 'false'})
  end

  def get_successor_possibs_json
    render :partial => 'layouts/filter_table', :locals => {:options => get_successor_possibs}
  end

  def like_sanitize(str)
    return '' if str.nil?
    str.sub('_', '\\_')
  end

  def sorting_add
    #sorting = Sorting.first(:conditions => {:table_name => params[:datensatz],
    #                      :col_name => params[:col_name],
    #                      :human_name => params[:human_name],
    #                      :user_id => session[:user]})

    sorting = Sorting.where(table_name: params[:datensatz],
                            col_name: params[:col_name],
                            human_name: params[:human_name],
                            user_id: session[:user]).take
    unless sorting.nil?
      redirect_to :action => "sorting_toggle", :id => sorting.id
    else
      max_priority = ActiveRecord::Base.connection.query("SELECT max(priority) FROM model.sortings
  WHERE user_id = #{session[:user]}
  AND table_name = '#{params[:datensatz]}'
  GROUP BY table_name")[0][0].to_i rescue 0
      sorting = Sorting.new(:table_name => params[:datensatz],
                            :col_name => params[:col_name],
                            :human_name => params[:human_name],
                            :priority => max_priority + 1)
      sorting.user_id = session[:user]
      sorting.save
      # render :text => 'ok'
      redirect_to :action => 'index'
    end
  end

  def sorting_del
    Sorting.destroy(params[:id])
    @gen = gen
    list = @gen.list_sortings
    i = 1
    if list[0].is_a?(Sorting)
      list.each do |s|
        s.update_attribute(:priority, i)
        i += 1
      end
    end
    # render :text => 'ok'
    redirect_to :action => 'index'
  end

  def sorting_toggle
    s = Sorting.find(params[:id])
    s.toggle!(:desc)
    # render :text => 'ok'
    redirect_to :action => 'index'
  end

  def change_order
    @gen = gen
    list = @gen.list_sortings
    sorting_order = params[:sorting_order]

    for i in (0..list.length - 1)
      s = list[i]
      n = sorting_order[i]
      s.update_attribute(:priority, n)
    end
    # render :text => 'ok'
    redirect_to :action => 'index'
  end

  def heading
    return self.class::PLURAL
  end
end
