class ModuleApp
  include Mongoid::Document
  include Mongoid::Timestamps
  # include OrbitCoreLib::ObjectTokenUtility
  # include OrbitApp::ModuleAppMembershipTools

  field :auth_approval_users, type: Array, default: nil
  field :auth_manager_users, type: Array, default: nil
  field :auth_sub_manager_users, type: Array, default: nil
  field :has_category, type: Boolean, default: false
  field :key
  field :title
  field :sidebar_order,type: Integer,default: 0

  has_one :auth_manager, dependent: :destroy
  has_many :auth_approvals, dependent: :destroy
  has_many :auth_sub_managers, dependent: :destroy
  has_many :categories, dependent: :destroy
  has_many :module_tags, dependent: :destroy

  has_many :approvals #to remove

  delegate :authorized_users, to: :auth_manager, prefix: true, allow_nil: true

  def refetch_setting!(reg)
    # %w{module_label category base_url version organization author intro update_info create_date}.each  do |field|
    #   self[field.to_sym] =  reg.send field 
    # end    
    self[:app_pages] = reg.get_app_pages
    self[:enable_frontend] = reg.get_enable_frontend
    self[:get_widget_style] = reg.get_widgets
    self[:using_default_widget] = !reg.get_default_widget.blank?
    self[:widgets] = reg.get_widgets
    self[:has_tag] = reg.get_has_tags
    self[:has_category] = reg.get_has_category
    self[:is_approvable] = reg.get_is_approvable
    self[:is_authorizable] = reg.get_is_authorizable
    self[:approvable_models] = reg.get_approvable_models
    self[:authorizable_models] = reg.get_authorizable_models
  end


  # scope :for_frontend_select,
  scope :standard_sorting ,order_by(:title, :asc)

  def self.for_widget_select
    where(:key.in=>OrbitApp::Module::WidgetUtility.all.keys).order_by(:title, :asc)
  end

  def self.for_frontend_select
    where(:key.in => OrbitApp::Module::FrontendUtility.all.keys).excludes(widgets: nil).where(enable_frontend: true).order_by(:title, :asc)
  end

  def enable_frontend?
    self[:enable_frontend]
  end

  def get_default_widget
    get_registration.get_default_widget
  end


  def get_widget_for_select
    widgets = get_widget_style
    ary = widgets.collect do |k,v| 
      if k == 'default_widget'
        [I18n.t('widget.default_widget'),'default_widget'] 
      else
        [I18n.t(v[:label]),k]   
      end
      
    end
  end

  # def get_widget_style
  #   get_registration.get_widgets
  # end

  def has_default_widget?
    self[:widgets].has_key? 'default_widget'  
  end

  def label
    I18n.t(label_i18n)
  end

  def label_i18n
    reg = get_registration
    reg.nil? ?  'Init is not defined completely' : get_registration.get_label_i18n
  end


  # def needs_to_widget_option?
  #   if self.widget_options
  #     self.widget_options.has_key? widgets.first
  #   else
  #     false  
  #   end
  # end

  def using_default_widget?
    # !get_registration.get_default_widget.blank?
    self[:get_default_widget]
  end

  def widget_fields
    # binding.pry
    # raise 'Need to link with OrbitApp [type: Array]'
    get_registration.get_default_widget_fields
  end

  # def widgets
  #   # get_registration.get_widgets
  #   # get_registration.get_default_widget
  # end

  def widget_options(widget_path=nil)
    get_registration.get_widget_by_path(widget_path)
    # raise 'Need to link with OrbitApp [type: Hash]'
  end

  def widget_options_fields_i18n
    raise 'Need to link with OrbitApp [type: Hash]'
  end

  def widget_fields_link_method
    get_registration.get_link_methods
    # raise 'Need to link with OrbitApp [type: Hash]'
  end


  has_many :managers,as: :managing_app ,:class_name => "AppManager" ,:dependent => :destroy#,:foreign_key => "managing_app_id",:inverse_of => :managing_app
  has_many :sub_managers,as: :sub_managing_app ,:class_name => "AppManager", :dependent => :destroy#,:foreign_key => "sub_managing_app_id",:inverse_of => :sub_managing_app
  
  # # has_many :tags
  has_many :page_parts
  has_many :pages
  
  has_one :app_auth,dependent: :delete

  def get_categories
    get_registration.get_categories
  end

  def module_name
    I18n.t(get_registration.get_label_i18n)
  end

  def get_registration
    OrbitApp::Module::Registration.find_by_key(key)
  end

  def self.find_by_key(key)
    self.where(key: key)[0] rescue nil
  end

  def sorted_tags_for_cloud
    temp_tags = {}
    self.tags.each{ |tag|
      temp_tags.merge!({tag => Tag.get_impressionist(tag)})
    }
    if !temp_tags.blank?
      sorted_tags = temp_tags.sort{|a,b| a[1]<=>b[1]}.reverse
      sorted_tags[0][1] = :hot1
      offset = (sorted_tags.size - 1) / 3
      i = 1
      class_i = 2
      sorted_tags[1..-1].collect!{ |x|
        x[1] = "hot#{class_i}"
        i == offset ? i = 1 : i += 1 if class_i < 4
        class_i += 1 if i == offset && class_i < 4
      }
      sorted_tags
    else
      []
    end
  end
  
  def tags
    self.module_tags.map{|t| t.tag }
  end


  # authorization
  def update_auth_approval_users
    user_ids = self.auth_approvals.inject([]) do |users, auth|
      users += auth.authorized_users.map{|user| user.id}
    end
    self.update_attribute(:auth_approval_users, user_ids.uniq)
  end

  def update_auth_manager_users
    users = self.auth_manager_authorized_users
    self.update_attribute(:auth_manager_users, users.map{|user| user.id}) if users
  end

  def update_auth_sub_manager_users
    user_ids = self.auth_sub_managers.inject([]) do |users, auth|
      auth = auth.class.find(auth.id)
      users += auth.authorized_users.map{|user| user.id}
    end
    self.update_attribute(:auth_sub_manager_users, user_ids.uniq)
  end

  def managers
    auth_manager_authorized_users || []
  end

  def user_can_manage?(user)
    managers.include?(user)
  end

  def is_manager?(user)
    if user && !auth_manager_users.blank?
      auth_manager_users.include?(user.id)
    else
      false
    end
  end
  
  def is_sub_manager?(user)
    if user && !auth_sub_manager_users.blank?
      auth_sub_manager_users.include?(user.id)
    else
      false
    end
  end
  
  def can_approve?(user)
    if user && !auth_approval_users.blank?
      auth_approval_users.include?(user.id)
    else
      false
    end
  end

end
