class EasyUserType < ActiveRecord::Base
  include Redmine::SafeAttributes

  has_many :users
  has_many :easy_custom_menus, ->{ order("COALESCE(#{EasyCustomMenu.table_name}.root_id, #{EasyCustomMenu.table_name}.id), #{EasyCustomMenu.table_name}.root_id, #{EasyCustomMenu.table_name}.id") }, :dependent => :destroy
  has_and_belongs_to_many :easy_user_visible_types, :join_table => 'easy_user_types_easy_user_types', :class_name => 'EasyUserType', :foreign_key => 'easy_user_visible_type_id', :association_foreign_key => 'easy_user_type_id'
  has_and_belongs_to_many :easy_user_visible_to_types, :join_table => 'easy_user_types_easy_user_types', :class_name => 'EasyUserType', :foreign_key => 'easy_user_type_id', :association_foreign_key => 'easy_user_visible_type_id'
  has_and_belongs_to_many :easy_queries, :join_table => "#{table_name_prefix}easy_queries_easy_user_types#{table_name_suffix}", :foreign_key => 'easy_user_type_id'

  has_many :visible_users, through: :easy_user_visible_types, class_name: 'User', source: :users

  belongs_to :default_page_template, class_name: 'EasyPageTemplate', foreign_key: 'easy_page_template_id', required: false

  accepts_nested_attributes_for :easy_custom_menus, :allow_destroy => true

  before_save :check_default
  before_destroy { !is_default? }
  before_destroy :set_default_before_destroy

  after_save :invalidate_visible_cache, :on => [:update]
  after_destroy :invalidate_visible_cache

  serialize :settings, Array

  validates :name, :presence => true, :uniqueness => true

  attr_protected :id

  scope :sorted, lambda { order("#{table_name}.position ASC") }
  scope :easy_type_internal, lambda { where(:internal => true) }
  scope :easy_type_external, lambda { where(:internal => false) }

  acts_as_positioned

  safe_attributes 'name', 'settings', 'internal', 'position', 'is_default', 'easy_custom_menus_attributes', 'submenus_attributes', 'reorder_to_position', 'easy_user_visible_type_ids', 'easy_user_visible_to_type_ids', 'show_in_meeting_calendar'
  safe_attributes 'easy_page_template_id'

  def self.default
    EasyUserType.where(:is_default => true).first
  end

  def self.available_settings
    {:top_menu => [:home_icon, :projects, :issues, :more, :custom_menu, :before_search, :search, :jump_to_project, :administration, :sign_out, :user_profile],
      :custom_menu => []}
  end

  def to_s
    self.name
  end

  def settings=(s)
    s = s.collect {|p| p.to_sym unless p.blank? }.compact.uniq if s
    write_attribute(:settings, s)
  end

  def easy_user_type_for?(setting)
    self.settings.include?(setting.to_sym) ? true : false
  end

  def easy_user_visible_type_ids=(user_types)
    if user_types.is_a?(Array) && user_types.include?('all')
      super(EasyUserType.all.pluck(:id))
    else
      super(user_types)
    end
  end

  def easy_user_visible_to_type_ids=(user_types)
    if user_types.is_a?(Array) && user_types.include?('all')
      super(EasyUserType.all.pluck(:id))
    else
      super(user_types)
    end
  end

  def safe_attributes=(attributes)
    # Submenu via nested_attributes can be only created
    # Its never updated or destroyed
    easy_custom_menus_attributes = attributes['easy_custom_menus_attributes'] || {}
    easy_custom_menus_attributes.each do |_, menu_attrs|
      submenus_attributes = menu_attrs['submenus_attributes']
      next if submenus_attributes.blank?

      submenus_attributes.each do |_, attrs|
        id = attrs['id']
        next if id.blank?

        if attrs.delete('_destroy').to_s.to_boolean
          EasyCustomMenu.destroy(id)
        else
          EasyCustomMenu.update(id, attrs)
        end
      end

      submenus_attributes.reject!{|_, attrs| attrs['id'].present?}
    end

    super

    easy_custom_menus.each do |menu|
      menu.submenus.each do |submenu|
        submenu.easy_user_type = self
      end
    end
  end

private

  def set_default_before_destroy
    Principal.where(:easy_user_type_id => self.id).update_all(:easy_user_type_id => self.class.default.id)
  end

  def check_default
    if self.is_default_changed?
      self.is_default? ? self.class.update_all(:is_default => false) : self.is_default = true
    end
  end

  def invalidate_visible_cache
    EasyUserType.pluck(:id).each do |i|
      Rails.cache.delete "user_visible_#{i}_#{self.id}"
      Rails.cache.delete "user_visible_#{self.id}_#{i}"
    end
  end

end
