class ApiJamTracksController < ApiController

  # have to be signed in currently to see this screen
  before_filter :api_signed_in_user, :except => [:index, :autocomplete, :show_with_artist_info, :artist_index]
  before_filter :api_any_user, :only => [:index, :autocomplete, :show_with_artist_info, :artist_index]
  before_filter :lookup_jam_track_right, :only => [:download, :enqueue, :show_jam_track_right, :mark_active, :download_stem]
  before_filter :ip_blacklist, :only => [:download_stem, :download]
  before_filter :user_blacklist, :only => [:download_stem, :download]


  respond_to :json

  def log
    @log || Logging.logger[ApiJamTracksController]
  end

  def show
    @jam_track = JamTrack.find(params[:id].to_s)
    render "api_jam_tracks/show_for_client", :layout => nil
  end

  def show_with_artist_info
    @jam_track = JamTrack.find_by_plan_code!(params[:plan_code])
  end

  def index    
    data = JamTrack.index(params, any_user)
    @jam_tracks, @next, @count = data[0], data[1], data[2]

    render "api_jam_tracks/index", :layout => nil
  end


  def mark_active
    mixdown_id = params[:mixdown_id]
    stem_id = params[:stem_id]

    # only one should be active at a time, so we enforce that on the server here. if you specify one, the other will get nulled automatically
    if mixdown_id
      stem_id = nil
    else
      mixdown_id = nil
    end
    @jam_track_right.last_mixdown_id = mixdown_id
    @jam_track_right.last_stem_id = stem_id
    @jam_track_right.save

    if @jam_track_right.errors.any?
      respond_with_model(@jam_track_right)
      return
    else
      @jam_track = @jam_track_right.jam_track
      render "api_jam_tracks/show_for_client", :layout => nil
    end

  end

  def autocomplete
    autocomplete = JamTrack.autocomplete(params, any_user)

    @artists = autocomplete[:artists]
    @songs = autocomplete[:songs]
    render "api_jam_tracks/autocomplete", :layout => nil
  end

  def artist_index
    data = JamTrack.artist_index(params, any_user)
    @artists, @next = data[0], data[1]

    render "api_jam_tracks/artist_index", :layout => nil
  end

  def played
    if params[:id].blank?
      render(:json => { :message => "JamTrack ID required" }, :status => 400) and return 
    end
    play = PlayablePlay.new
    play.player_id = current_user.id
    play.ip_address = request.remote_ip

    unless current_user.first_played_jamtrack_at
      User.where(id: current_user.id).update_all(first_played_jamtrack_at: Time.now)
      current_user.first_played_jamtrack_at = Time.now
    end

    # VRFS-2916 jam_tracks.id is varchar: REMOVE
    # play.jam_track = JamTrack.where(id: params[:id].to_i).first
    # VRFS-2916 jam_tracks.id is varchar: ADD
    play.playable = JamTrack.where(id: params[:id]).first

    play.save

    if play.errors.any?
      render :json => { :message => "Unexpected error occurred" }, :status => 422
    else
      render :json => {}, :status => 201
    end
  end

  def _handlePurchasedHead
    if jtid = params[:id]
      if params[:mixcheck]
        checksum = JamTrackMixdown.mixdownChecksum(current_user.id, jtid)
        head :ok, checksum: checksum
      else
        # 204: nothing purchased for user
        # 200: jamtrack purchase for user confirmed
        if JamTrackRight
            .where(jam_track_id: jtid, user_id: current_user.id)
            .limit(1)
            .blank?
          head(:no_content)
        end
      end
    elsif params[:syncbuys].present?
      head :ok, purchasecount: JamTrackRight.where(user_id: current_user.id).count
    end
    head(:ok) unless performed?
  end

  def purchased
    if request.head? || (request.get? && 1 == params[:head].to_i)
      self._handlePurchasedHead 
      return
    end
    if params[:mobile]
      @jam_tracks = JamTrack.purchase_stubs(current_user).to_a
      response.headers['total-entries'] = @jam_tracks.count.to_s
      render "api_jam_tracks/purchased_mobile", :layout => nil
      return
    end
    params[:show_purchased_only] = true
    data = JamTrack.index(params, current_user)
    @jam_tracks, @next = data[0], data[1]

    response.headers['total-entries'] = @jam_tracks.total_entries.to_s

    render "api_jam_tracks/purchased", :layout => nil
  end

  def download_stem

    if current_user.email_needs_verification
      render :json => { :message => "verify email" }, :status => 403
      return
    end

    if @jam_track_right.valid?

      if params[:stem_id] == 'master'
        jam_track_track = @jam_track_right.jam_track.master_track
      else
        jam_track_track = JamTrackTrack.find(params[:stem_id])
      end

      if params[:download]
        if !@jam_track_right.can_download && params[:client_type] != 'ios' # let iOS slip through when passing in download param
          render :json => { :message => "Download rights not purchased"}, :status => 403
          return
        end

        if DownloadTracker.check(current_user, request.remote_ip, jam_track_track, !@jam_track_right.redeemed, params[:mark], false)
          render :json => { :message => "IP blacklisted"}, :status => 403
          return
        end

        redirect_to jam_track_track.web_download_sign_url(120, params[:file_type], 'application/octet-stream', "attachment; filename=\"#{@jam_track_right.jam_track.name + '-' + jam_track_track.display_name}.mp3\"")
      else
        if DownloadTracker.check(current_user, request.remote_ip, jam_track_track, !@jam_track_right.redeemed, params[:mark], true)
          render :json => { :message => "IP blacklisted"}, :status => 403
          return
        end

        redirect_to jam_track_track.web_download_sign_url(120, params[:file_type])
      end

    else
      render :json => { :message => "download limit surpassed", :errors=>@jam_track_right.errors }, :status => 403
    end
  end

  def download
    if current_user.email_needs_verification
      render :json => { :message => "verify email" }, :status => 403
      return
    end

    if @jam_track_right.valid?

      fingerprint = params[:mark]

      if DownloadTracker.check(current_user, request.remote_ip, @jam_track_right.jam_track, !@jam_track_right.redeemed, fingerprint, jkclient_agent?)
        render :json => { :message => "IP blacklisted"}, :status => 403
        return
      end

      all_fingerprint = params[:all_fp]
      running_fingerprint = params[:running_fp]

      if Rails.application.config.guard_against_fraud
        error = @jam_track_right.guard_against_fraud(current_user, {all:all_fingerprint, running: running_fingerprint}, request.remote_ip)
        if error
          log.warn("potential fraud detected: #{error}")
          render :json => { :message => error }, :status => 403
          return
        end
      end

      sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i
      if @jam_track_right && @jam_track_right.ready?(sample_rate)
        @jam_track_right.update_download_count
        now = Time.now
        @jam_track_right.last_downloaded_at = now
        @jam_track_right.first_downloaded_at = now if @jam_track_right.first_downloaded_at.nil?
        @jam_track_right.save!

        is_jamblaster = !!params[:is_jamblaster]

        # if it's not the jamblaster, keep the URL https
        redirect_to @jam_track_right.sign_url(120, sample_rate, !is_jamblaster)
      else
        @jam_track_right.enqueue_if_needed(sample_rate)
        render :json => { :message => "not available, digitally signing Jam Track offline." }, :status => 202
      end
    else
      render :json => { :message => "download limit surpassed", :errors=>@jam_track_right.errors }, :status => 403
    end        
  end

  def enqueue

    fingerprint = params[:fingerprint]

    if Rails.application.config.guard_against_fraud
      error = @jam_track_right.guard_against_fraud(current_user, fingerprint, request.remote_ip)
      if error
        log.warn("potential fraud detected: #{error}")
        render :json => { :message => error }, :status => 403
        return
      end
    end

    sample_rate = params[:sample_rate].nil? ? nil : params[:sample_rate].to_i
    enqueued = @jam_track_right.enqueue_if_needed(sample_rate)
    log.debug("jamtrack #{enqueued ? "ENQUEUED" : "NOT ENQUEUED"}: jam_track_right=#{@jam_track_right.id} sample_rate=#{sample_rate} ")
    render :json => { :message => "enqueued" }, :status => 200
  end

  def show_jam_track_right

  end

  def keys
    puts "Keys"
    puts "--------------------------"
    jamtrack_holder = params[:jamtracks]
    puts jamtrack_holder.inspect

    unless jamtrack_holder.kind_of?(Hash)
      render :json => {message: 'jamtracks parameter must be an hash'}, :status => 422
      return
    end

    jamtracks = jamtrack_holder[:tracks]

    unless jamtracks.kind_of?(Array)
      render :json => {message: 'jamtracks:tracks parameter must be an array'}, :status => 422
      return
    end


    # jamtracks come in the form id-44 or id-48, so we need to do a little extra parsing
    # mixdowns come in the form id_mixid-44 or id_mixid-48, so we also need to handle that

    jamtrack_ids = Set.new
    jamtracks_fq_ids = Set.new
    jamtrack_mixdowns = {}

    jamtracks.each do |jamtrack|
      rindex = jamtrack.rindex('-')
      if rindex
        id = jamtrack[0..(rindex-1)]

        # let's see if a mixid is in this ID
        rindex = id.rindex('_')

        if rindex
          # ok, this is id_mixid-44 format; so we need to parse again for the ID
          just_id = jamtrack[0..(rindex-1)]
          sample_rate = jamtrack[-2..-1]

          jamtrack_ids << just_id

          simulated_fq_id = "#{just_id}-#{sample_rate}"
          mixdown_info = jamtrack_mixdowns[simulated_fq_id]

          unless mixdown_info
            mixdown_info = []
            jamtrack_mixdowns[simulated_fq_id] = mixdown_info
          end
          mixdown_info << id

        else
          jamtrack_ids << id
        end


        jamtracks_fq_ids << jamtrack # includes sample rate
      end
    end

    @jam_tracks = JamTrackRight.list_keys(current_user, jamtrack_ids)
    @jamtracks_fq_ids = jamtracks_fq_ids
    @jamtrack_mixdowns = jamtrack_mixdowns
    puts "jamtrack_mixdowns #{jamtrack_mixdowns}"
  end

  def ios_order_placed
    jam_track = JamTrack.find(params[:jam_track_id])

    begin
      Sale.ios_purchase(current_user, 
                        jam_track, 
                        params[:receipt], 
                        params[:price_data],
                        params[:variant])
    rescue
      response = { message: $!.to_s }
      render :json => response, :status => 422
      return
    end

    response = {name: jam_track.name, id: jam_track.id, jam_track_right_id: jam_track.right_for_user(current_user).id, version: jam_track.version}
    render :json => response, :status => 200
  end

private
  def lookup_jam_track_right
    @jam_track_right = JamTrackRight.where("jam_track_id=? AND user_id=?", params[:id], current_user.id).first
    raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR unless @jam_track_right
  end

end # class ApiJamTracksController
