class EasyPageLayoutController < ApplicationController

  before_action :find_project
  before_action :find_page, :only => [:add_module, :order_module, :save_module]
  before_action :find_zone, :only => [:add_module, :order_module]
  before_action :find_zone_module, :only => [:clone_module]
  before_action :find_user, :only => [:clone_module]
  before_action :add_tab_to_back_url, :only => [:save_module]

  def add_module
    @user = User.current
    begin
      available_module = EasyPageAvailableModule.find(params[:module_id])
    rescue ActiveRecord::RecordNotFound
      render_404
      return
    end

    user = User.find(params[:user_id]) unless params[:user_id].nil?
    user_id = user.id unless user.nil?
    tab = params[:t].to_i
    tab = 1 if tab <= 0
    page_tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]
    page_tab ||= EasyPageUserTab.where(:page_id => @page.id, :user_id => user_id, :entity_id => params[:entity_id], :position => tab).first

    page_module = EasyPageZoneModule.new(:easy_pages_id => @page.id, :easy_page_available_zones_id => @zone.id, :easy_page_available_modules_id => available_module.id, :user_id => user_id, :entity_id => params[:entity_id], :tab => tab, :tab_id => (page_tab && page_tab.id), :settings => available_module.module_definition.default_settings || HashWithIndifferentAccess.new)
    page_module.position = 1
    page_module.save!

    edit = params[:edit].nil? || params[:edit].to_boolean
    render_single_easy_page_module(page_module, nil, @page, user, nil, params[:back_url], edit, true, {:project => @project})
  end

  def clone_module
    new_zone_module = @zone_module.dup
    new_zone_module.position = @zone_module.position.to_i
    new_zone_module.save!

    render_single_easy_page_module(
      new_zone_module,  # page_module
      nil,              # page_module_render_settings = nil
      nil,              # page = nil
      @user,            # user = nil
      nil,              # entity_id = nil
      nil,              # back_url = nil
      true,             # edit = nil
      true,             # with_container = false
      project: @project # page_context = {}
    )
  end

  def remove_module
    begin
      pzm = EasyPageZoneModule.find(params[:uuid].dasherize)
    rescue ActiveRecord::RecordNotFound
    end
    pzm.destroy if pzm

    render :nothing => true
  end

  def order_module
    remaining_modules_in_zone = (params["list-#{@zone.zone_definition.zone_name.dasherize}"] || [])
    tab = params[:t].to_i
    tab = 1 if tab <= 0

    #EasyPageZoneModule.transaction do
    if (remaining_modules_in_zone.size > 0)
      scope = EasyPageZoneModule.where(:easy_pages_id => @page.id)
      scope = scope.where(:easy_page_available_zones_id => @zone.id)
      scope = scope.where(:tab => tab)
      scope = scope.where("#{EasyPageZoneModule.table_name}.uuid NOT IN (?)", remaining_modules_in_zone)

      if params[:user_id].blank?
        scope = scope.where(:user_id => nil)
      else
        scope = scope.where(:user_id => params[:user_id].to_i)
      end

      if params[:entity_id].blank?
        scope = scope.where(:entity_id => nil)
      else
        scope = scope.where(:entity_id => params[:entity_id].to_i)
      end

      scope.update_all(:easy_page_available_zones_id => -1)
    end

    position = 0
    remaining_modules_in_zone.each do |uuid|
      position += 1
      EasyPageZoneModule.where(:uuid => uuid).update_all(:easy_page_available_zones_id => @zone.id, :position => position)
    end

    EasyPageZoneModule.where(:easy_pages_id => @page.id).where(:easy_page_available_zones_id => -1).update_all(:easy_page_available_zones_id => @page.zones.first.id)
    #end

    render :nothing => true
  end

  def save_module
    @page.user_modules(params[:user_id], params[:entity_id], nil, :all_tabs => true).each do |zone_name, user_modules|
      user_modules.each do |user_module|
        next unless params[user_module.module_name]
        user_module.settings = params[user_module.module_name]
        user_module.save
      end
    end

    redirect_back_or_default(:controller => 'my', :action => 'page')
  end

  def layout_from_template
    begin
      page_template = EasyPageTemplate.find(params[:page_template_id].to_i)
    rescue ActiveRecord::RecordNotFound
      redirect_to params[:back_url]
      return
    end

    EasyPageZoneModule.create_from_page_template(page_template, params[:user_id], params[:entity_id])

    redirect_back_or_default(:controller => 'my', :action => 'page')
  end

  def layout_from_template_selecting_projects
    respond_to do |format|
      format.html { render :layout => 'base' }
    end
  end

  def layout_from_template_selected_projects
    begin
      page_template = EasyPageTemplate.find(params[:page_template_id].to_i)
    rescue ActiveRecord::RecordNotFound
      redirect_to params[:back_url]
      return
    end

    begin
      projects = Project.find(params[:projects])
    rescue ActiveRecord::RecordNotFound
      return render_404
    end

    projects.each do |project|
      EasyPageZoneModule.create_from_page_template(page_template, nil, project.id)
    end

    flash[:notice] = l(:notice_template_successful_applied)
    redirect_back_or_default(:controller => 'my', :action => 'page')
  end

  def layout_from_template_selecting_users
    @users = User.active.sorted
    @groups = Group.joins(:users).where(:users_users => {:status => User::STATUS_ACTIVE}).uniq.sorted

    respond_to do |format|
      format.html { render :layout => 'base' }
    end
  end

  def layout_from_template_selected_users
    begin
      page_template = EasyPageTemplate.find(params[:page_template_id].to_i)
    rescue ActiveRecord::RecordNotFound
      redirect_back_or_default({:controller => 'easy_pages'})
      return
    end

    if params[:users]
      User.where(:id => params[:users]).each do |user|
        EasyPageZoneModule.create_from_page_template(page_template, user.id, params[:entity_id])
      end
    end

    flash[:notice] = l(:notice_template_successful_applied)
    redirect_back_or_default(:controller => 'my', :action => 'page')
  end

  def layout_from_template_to_all
    begin
      page_template = EasyPageTemplate.find(params[:page_template_id].to_i)
    rescue ActiveRecord::RecordNotFound
      redirect_to params[:back_url]
      return
    end
    page = page_template.page_definition
    actions = params[:actions].to_s.split(',')

    User.all.each do |user|
      EasyPageZoneModule.create_from_page_template(page_template, user.id, params[:entity_id])
    end if actions.include?('users')

    Redmine::Hook.call_hook(:controller_easy_page_layout_layout_from_template_to_all, {:page_template => page_template, :page => page, :actions => actions})

    flash[:notice] = l(:notice_template_successful_applied)
    redirect_back_or_default(:controller => 'my', :action => 'page')
  end

  def save_grid
    unless data = params[:page_modules]
      render nothing: true
      return
    end

    modules = EasyPageZoneModule.where(uuid: data.keys)
    modules.each do |epzm|
      epzm.settings['gridstack'] = data[epzm.uuid]
      epzm.save
    end

    render nothing: true
  end

  def get_tab_content
    @page = EasyPage.find(params[:page_id]) if params[:page_id]
    @tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]
    user = User.find(params[:user_id]) if params[:user_id]

    @layout_style = @page.layout_path

    render_action_as_easy_tab_content(@tab, @page, user, params[:entity_id], nil, true)

  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def show_tab
    @tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]
    @selected_tab = params[:t].to_i if params[:t]
    is_preloaded = params[:is_preloaded].to_s.to_boolean

    if @tab
      respond_to do |format|
        format.html { render :partial => 'common/easy_page_editable_tabs_inline_show', :locals => {:tab => @tab, :editable => true, :selected_tab => @selected_tab, :is_preloaded => is_preloaded} }
        format.js { @is_preloaded = is_preloaded }
      end
    else
      render :nothing => true
    end
  end

  def add_tab
    page = EasyPage.find(params[:page_id])
    user = User.find(params[:user_id]) if params[:user_id]
    entity_id = params[:entity_id]

    @tab = EasyPageUserTab.add(page, user, entity_id)
    @tabs = EasyPageUserTab.page_tabs(page, user, entity_id)

    respond_to do |format|
      format.html {
        if @tabs && @tabs.size > 0
          render(:partial => 'common/easy_page_editable_tabs', :locals => {:tabs => @tabs, :editable => true, :selected_tab => @tab.position})
        else
          render :nothing => true
        end
      }
      format.js {
        if @tabs && @tabs.size > 0
          @page = page
          @layout_style = @page.layout_path.match(/\/([^\/]+)$/)[1]
          render_action_as_easy_tab_content(@tab, page, user, entity_id, nil, true)
          easy_page_context[:page_params][:current_tab] = @tab
        else
          render :nothing => true
        end
      }
    end
  end

  def edit_tab
    tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]

    if tab
      render :partial => 'common/easy_page_editable_tabs_inline_edit', :locals => {:tab => tab, :editable => true, :is_preloaded => params[:is_preloaded]}
    else
      render :nothing => true
    end
  end

  def save_tab
    tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]
    if params[:t]
      selected_tab = params[:t].to_i
    end
    is_preloaded = params[:is_preloaded].to_s.to_boolean

    if tab
      tab.name = params[:name] if params[:name]
      tab.reorder_to_position = params[:reorder_to_position] if params[:reorder_to_position]
      tab.save
      respond_to do |format|
        format.html { render :partial => 'common/easy_page_editable_tabs_inline_show', :locals => {:tab => tab, :editable => true, :selected_tab => selected_tab, :is_preloaded => is_preloaded} }
        format.js { @tab = tab; @selected_tab = selected_tab; @is_preloaded = is_preloaded }
        format.json { render :nothing => true }
      end
    else
      render :nothing => true
    end
  end

  def remove_tab
    tab = EasyPageUserTab.find(params[:tab_id]) if params[:tab_id]
    if tab
      EasyPageZoneModule.delete_modules(tab.page_definition, params[:user_id], params[:entity_id], tab.id)
    end

    page = EasyPage.find(params[:page_id])
    user = User.find(params[:user_id]) if params[:user_id]
    entity_id = params[:entity_id]

    tabs = EasyPageUserTab.page_tabs(page, (user && user.id), entity_id)

    if request.xhr?
      respond_to do |format|
        format.html {
          if tabs && tabs.size > 0
            selected_tab = params[:t].to_i
            selected_tab = 1 if selected_tab <= 0

            render(:partial => 'common/easy_page_editable_tabs', :locals => {:tabs => tabs, :editable => true, :selected_tab => selected_tab})
          else
            render :nothing => true
          end
        }
        format.js {
          if tabs && tabs.size > 0 && tab && tab.id == params[:tab_id].to_i
            js_script = "
              PageLayout.tab_element.easytabs('select', '#easy_jquery_tab_panel-#{tabs.first.id}');"
          elsif tabs && tabs.size < 1
            original_url = CGI.unescape(params[:original_url])
            js_script = "window.location.href='#{original_url}';"
          end
          if js_script
            render :status => :ok, :text => js_script
          else
            render :nothing => true
          end
        }
      end
    else
      original_url = CGI.unescape(params[:original_url])
      original_url.gsub!(/tab=\d+/, '')
      redirect_to(original_url)
    end
  end

  def get_group_entities
    user = User.current
    return render_404 unless (page_module = EasyPageZoneModule.find_by_uuid(params[:page_module_id]))
    data = page_module.get_show_data(user, params[:query], :project => @project, :load_group => loading_group)
    query = data[:query]
    sort_init(query.sort_criteria_init)
    sort_update(query.sortable_columns, "#{self.sort_name}_#{params[:page_module_id]}")

    if prepare_easy_query_render(query, order: query.sort_criteria_to_sql_order.presence) && loading_group?
      render_easy_query_html(query)
    else
      render :inline => l(:label_easy_page_module_settings_missing)
    end
  end

  def toggle_members
    group = Group.find(params[:group_id])
    user_fields = group.users.map { |user| "users_#{user.id}" }
    render :js => "fields = #{user_fields.to_json}; $(fields).each(function(f) {EASY.utils.toggleCheckbox(fields[f])})"
  end

  private

  def find_project
    @project = Project.find(params[:project_id]) unless params[:project_id].blank?
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def find_page
    @page = EasyPage.find(params[:page_id])
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def find_zone
    @zone = EasyPageAvailableZone.find(params[:zone_id])
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def find_zone_module
    @zone_module = EasyPageZoneModule.find(params[:uuid])
  rescue ActiveRecord::RecordNotFound
    render_404
  end

  def find_user
    @user = User.find(params[:user_id]) unless params[:user_id].nil?
  rescue ActiveRecord::RecordNotFound
    render_404
  end

end
