class User
  include Mongoid::Document
  include Mongoid::Timestamps

  field :username, type: String
  field :first_name, type: String
  field :last_name, type: String
  field :biola_id, type: Integer # probably not needed once we have the trogdir_id
  field :title, type: String
  field :email, type: String
  field :photo_url, type: String
  field :department, type: String
  field :affiliations, type: Array, default: []
  field :entitlements, type: Array, default: []
  field :ferpa_eligible, type: Boolean, default: false
  field :permitted_groups, type: Array, default: []

  alias_attribute :netid, :username

  # for logging in
  field :current_login_at, type: DateTime
  field :last_login_at, type: DateTime
  field :login_count, type: Integer

  has_many :emails

  alias_attribute :netid, :username

  scope :limited_group_permissions, -> { User.not.where(:permitted_groups.all => GroupSetting.groups) }
  scope :permitted_to_send_to, -> group { where(permitted_groups: group ) }
  scope :custom_search, -> query {
    begin
      if query.present?
        nested_conditions = []
        # We need to take into account first and last name, which is why we split up the query
        #   and link all the words together with an '$and' filter so all the words need to match something.
        query.split.each do |q|
          fields = [:first_name, :last_name, :username, :email]
          conditions = fields.map {|f| {f => Regexp.new("^#{q}", Regexp::IGNORECASE)}}
          nested_conditions << {'$or' => conditions}
        end
        where('$and' => nested_conditions)
      end
    rescue RegexpError
      User.none
    end
  }

  def name
    [first_name, last_name].join(' ').strip
  end

  def admin?
    self.has_role?(:admin) || self.has_role?(:developer)
  end

  def developer?
    self.has_role?(:developer)
  end

  def has_role?(*roles)
    (self.roles & roles).any?
  end

  def roles
    (Array(affiliations) + relevant_entitlements).map(&:to_sym)
  end

  alias :to_s :name

  private

  # Find URNs that match the namespaces and remove the namespace
  # See http://en.wikipedia.org/wiki/Uniform_Resource_Name
  def relevant_entitlements
    urns = Array(entitlements)
    nids = Settings.urn_namespaces

    return [] if urns.blank?

    clean_urns = urns.map { |e| e.gsub(/^urn:/i, '') }
    clean_nids = nids.map { |n| n.gsub(/^urn:/i, '') }

    clean_urns.map { |urn|
      clean_nids.map { |nid|
        urn[0...nid.length] == nid ? urn[nid.length..urn.length] : nil
      }
    }.flatten.compact
  end

  def self.role_to_entitlement(role)
    Settings.urn_namespaces.map do |namespace|
      "#{namespace}#{role}"
    end
  end
end
