module JamRuby
  class InvitedUser < ActiveRecord::Base

    VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i

    attr_accessible :email, :sender_id, :autofriend, :note
    attr_accessor :accepted_twice

    self.primary_key = 'id'

    ### Who sent this invitatio?
    # either admin_sender or user_sender is not null.  If an administrator sends the invitation, then
    belongs_to :sender , :inverse_of => :invited_users, :class_name => "JamRuby::User", :foreign_key => "sender_id"

    # who is the invitation sent to?
    validates :email, :presence => true, format: {with: VALID_EMAIL_REGEX}
    validates :autofriend, :inclusion => {:in => [nil, true, false]}
    validates :invitation_code, :presence => true
    validates :note, length: {maximum: 400}, no_profanity: true # 400 == arbitrary.

    validate :valid_personalized_invitation
    validate :not_accepted_twice
    validate :can_invite?

    after_save :track_user_progression

    # ensure invitation code is always created
    before_validation(:on => :create) do
      self.invitation_code = SecureRandom.urlsafe_base64 if self.invitation_code.nil?
      self.sender_id = nil if self.sender_id.blank? # this coercion was done just to make activeadmin work
    end

    def track_user_progression
      self.sender.update_progression_field(:first_invited_at) unless self.sender.nil?
    end

    def self.index(user)
      return InvitedUser.where(:sender_id => user).order(:updated_at)
    end

    def sender_display_name
      return sender.name
    end

    def accept!
      if self.accepted
        accepted_twice = true
      end

      self.accepted = true
    end

    def invited_by_administrator?
      sender.nil? || sender.admin # a nil sender can only be created by someone using jam-admin
    end
    private

    def can_invite?
      errors.add(:sender, "can not invite others") if !invited_by_administrator? && !sender.can_invite?
    end

    def valid_personalized_invitation
      errors.add(:autofriend, "must be true if sender is specified") if autofriend && sender.nil?
    end

    def not_accepted_twice
      errors.add(:accepted, "you can only accept an invitation once") if accepted_twice
    end
  end
end
