module JamRuby
  class ClaimedRecording < ActiveRecord::Base
    include HtmlSanitize
    html_sanitize strict: [:name, :description]

    attr_accessible :name, :description, :is_public, :genre_id, :recording_id, :user_id, :upload_to_youtube, as: :admin

    belongs_to  :recording, :class_name => "JamRuby::Recording", :inverse_of => :claimed_recordings, :foreign_key => 'recording_id'
    belongs_to  :user, :class_name => "JamRuby::User", :inverse_of => :claimed_recordings
    belongs_to  :genre, :class_name => "JamRuby::Genre"
    has_many    :recorded_tracks, :through => :recording, :class_name => "JamRuby::RecordedTrack"
    has_many    :playing_sessions, :class_name => "JamRuby::ActiveMusicSession"
    has_many    :likes, :class_name => "JamRuby::RecordingLiker", :foreign_key => "claimed_recording_id", :dependent => :destroy
    has_many    :plays, :class_name => "JamRuby::PlayablePlay", :foreign_key => "claimed_recording_id", :dependent => :destroy
    has_many    :performance_samples, :class_name => "JamRuby::PerformanceSample", :foreign_key => "claimed_recording_id", :dependent => :destroy
    has_one     :share_token, :class_name => "JamRuby::ShareToken", :inverse_of => :shareable, :foreign_key => 'shareable_id', :dependent => :destroy

    validates :name, no_profanity: true, length: {minimum: 3, maximum: 64}, presence: true
    validates :description, no_profanity: true, length: {maximum: 8000}
    validates :is_public, :inclusion => {:in => [true, false]}
    validates :upload_to_youtube, :inclusion => {:in => [true, false]}
  
    validates :genre, presence: true
    validates :user, presence: true
    validates_uniqueness_of :user_id, :scope => :recording_id
    validate :user_belongs_to_recording


    before_create   :generate_share_token

    SHARE_TOKEN_LENGTH = 8
    FIXNUM_MAX = (2**(0.size * 8 -2) -1)

    def video_id
      recording.external_video_id
    end

    def user_belongs_to_recording
      if user && recording && !recording.users.exists?(user.id)
        errors.add(:user, ValidationMessages::NOT_PART_OF_RECORDING)
      end
    end
    # user must own this object
    # params is a hash, and everything is optional
    def update_fields(user, params)
      if user != self.user
        raise JamPermissionError, "user doesn't own claimed_recording"
      end

      self.name = params[:name]
      self.description = params[:description]
      self.genre = Genre.find_by_id(params[:genre]) unless params[:genre].nil?
      self.is_public = params[:is_public] unless params[:is_public].nil?
      save
    end

    def discard(user)
      if user != self.user
        raise JamPermissionError, "user doesn't own claimed_recording"
      end

      ClaimedRecording.where(:id => id).update_all(:discarded => true )

      recording.discard(user)
    end


    def has_mix?
      recording.has_mix?
    end

    def can_download?(some_user)
      !ClaimedRecording.find_by_user_id_and_recording_id(some_user.id, recording_id).nil?
    end

    def remove_non_alpha_num(token)
      token.gsub(/[^0-9A-Za-z]/, '')
    end

    # right now, the only thing that is brought back is ClaimedRecordings, and you can only query your own favorites
    def self.index_favorites(user, params = {})
      limit = params[:limit]
      limit ||= 20
      limit = limit.to_i

      # validate sort
      sort = params[:sort]
      sort ||= 'date'
      raise "not valid sort #{sort}" unless sort == "date"

      start = params[:start].presence
      start ||= 0
      start = start.to_i


      type_filter = params[:type]
      type_filter ||= 'claimed_recording'
      raise "not valid type #{type_filter}" unless type_filter == "claimed_recording"

      target_user = params[:user]

      raise JamPermissionError, "must specify current user" unless user
      raise "user must be specified" unless target_user

      if target_user != user.id
        raise JamPermissionError, "unable to view another user's favorites"
      end

      query = ClaimedRecording.limit(limit).order('created_at DESC').offset(start)
      query = query.joins(:likes)
      query = query.where('favorite = true')
      query = query.where("recordings_likers.liker_id = '#{target_user}'")
      query = query.where("claimed_recordings.is_public = TRUE OR claimed_recordings.user_id = '#{target_user}'")

      if query.length == 0
        [query, nil]
      elsif query.length < limit
        [query, nil]
      else
        [query, start + limit]
      end
    end

    private

    def generate_share_token
      token = loop do
        token = SecureRandom.urlsafe_base64(SHARE_TOKEN_LENGTH, false)
        token = remove_non_alpha_num(token)
        token.upcase!
        break token unless ShareToken.exists?(token: token)
      end

      self.share_token = ShareToken.new
      self.share_token.token = token
      self.share_token.shareable_type = "recording"
    end
  end
end
