require "mongoid"

module Devops
  module Model
    class Role

      include ::Mongoid::Document
      include ::Mongoid::Timestamps::CreatedInt
      include ::ActiveModel::Validations

      store_in collection: "roles"

      SUPER_USER_ROLE = 'super_user'

      field :_id, as: :'id', overwrite: true, type: String, default: ->{ self.name.downcase.gsub(%r(\s+), "_") if self.name }
      field :name, type: String
      field :description, type: String
      field :policies, type: Array, default: ->{ [] }

      validates_presence_of :id, message: "'id' is undefined"
      validates_uniqueness_of :id, on: :create

      validates_presence_of :name, message: "'name' is undefined"
      validates_format_of :name, with: /\A[\w\s]{1,99}\z/, message: "invalid name"

      validates_length_of :description, maximum: 500

      validates_presence_of :policies, message: "'policies' is undefined"

      validate :validate_policies

      def initialize hash
        raise InvalidRecord.new("Parameter 'name' is not a string") unless hash["name"].is_a?(String)
        raise InvalidRecord.new("Parameter 'description' is not a string") unless hash["description"].is_a?(String)
        raise InvalidRecord.new("Parameter 'policies' is not an array") unless hash["policies"].is_a?(Array)
        super(hash)
      end

      def validate_policies
        res = self.class.check_policies(self.policies)
        errors.add(:policies, res) unless res.nil?
      end

      def to_hash
        hash = self.attributes
        hash["id"] = hash.delete("_id")
#        hash["created_at"] = hash.delete("created_at").to_i if hash["created_at"]
        hash
      end

      def self.check_policies policies
        if policies.nil?
          return "Policies parameter can not be null, it must be an array"
        end
        available_policies = Devops::Api3.policies.keys
        if policies.include?("all")
          policies.clear
          policies.push 'all'
        else
          invalid_policies = []
          policies.each do |p|
            if p.is_a?(String)
              invalid_policies.push(p) unless available_policies.include?(p.to_sym)
            else
              return "Invalid value '#{p}': policy must be a string"
            end
          end
          unless invalid_policies.empty?
            return "Invalid policies: #{invalid_policies.join(', ')}"
          end
        end
        return nil
      end

    end
  end
end
