class ApiBandsController < ApiController

  before_filter :api_signed_in_user, :except => [:index, :show, :follower_index]
  before_filter :auth_band_member, :only => [:update, 
                :recording_create, :recording_update, :recording_destroy,
                :invitation_index, :invitation_show, :invitation_create, :invitation_destroy,
                :update_photo, :delete_photo, :generate_filepicker_policy]
  before_filter :auth_band_admin, :only => [:delete]

  respond_to :json

  def index
    @bands = Band.paginate(page: params[:page])
  end

  def show
    @band = Band.find(params[:id])
    respond_with_model(@band)
  end

  def delete
    @band.try(:destroy)
    respond_with @band, responder => ApiResponder
  end

  def create
    @band = Band.save(current_user, params)

    respond_with_model(@band, new: true, location: lambda { return api_band_detail_url(@band.id) })
  end

  def update
    @band = Band.save(current_user, params)

    respond_with_model(@band)
  end

  def validate
    @band = Band.build_band(current_user, params)
    @band.valid?

    respond_with_model(@band)
  end

  def musician_index
    if !params[:pending].blank?
      @musicians = Band.pending_musicians(params[:id])
    else
      unless params[:id].blank?
        @musicians = Band.musician_index(params[:id])

      else
        render :json => { :message => "Band ID is required." }, :status => 400
      end
    end
  end

  def musician_create
  end

  def musician_destroy
    unless params[:id].blank? || params[:user_id].blank?
      BandMusician.delete_all "(band_id = '#{params[:id]}' AND user_id = '#{params[:user_id]}' AND admin = 'f')"
    end
    render :json => {}, :status => 202
  end

  ###################### FOLLOWERS ########################
  def liker_index
    # NOTE: liker_index.rabl template references the likers property
    @band = Band.find(params[:id])
  end

  ###################### FOLLOWERS ########################
  def follower_index
    # NOTE: follower_index.rabl template references the followers property
    @band = Band.find(params[:id])
  end

  ###################### RECORDINGS #######################
  def recording_index
    @recordings = Band.recording_index(current_user, params[:id])
    respond_with @recordings, responder: ApiResponder, :status => 200
  end

  def recording_show
    hide_private = false
    band = Band.find(params[:id])

    # hide private Recordings from anyone who's not in the Band
    unless band.users.exists? current_user
      hide_private = true
    end

    @recording = Recording.find(params[:recording_id])
    if !@recording.public && hide_private
      render :json => { :message => "You are not allowed to access this recording." }, :status => 403
      #respond_with "You are not allowed to view this recording.", responder: ApiResponder, :status => 403
    else
      respond_with @recording, responder: ApiResponder, :status => 200
    end
  end

  def recording_create
    @recording = Recording.save(params[:recording_id],
                   params[:public],
                   params[:description],
                   params[:genres],
                   current_user.id,
                   params[:id],
                   true)

    respond_with @recording, responder: ApiResponder, :status => 201, :location => api_band_recording_detail_url(@band, @recording)
  end

  def recording_update
    @recording = Recording.save(params[:recording_id],
                                params[:public],
                                params[:description],
                                params[:genres],
                                current_user.id,
                                params[:id],
                                false)

    respond_with @recording, responder: ApiResponder, :status => 200
  end

  def recording_destroy
    @recording = Recording.find(params[:recording_id])

    unless @recording.nil?
      @recording.delete
      respond_with responder: ApiResponder, :status => 204
    end

    # no recording was found with this ID
    render :json => { :message => ValidationMessages::RECORDING_NOT_FOUND }, :status => 404 
  end

  ###################### INVITATIONS ######################
  def invitation_index
    @invitations = @band.invitations
    respond_with @invitations, responder: ApiResponder, :status => 200
  end

  def invitation_show
    begin
      @invitation = BandInvitation.find(params[:invitation_id])
      respond_with @invitation, responder: ApiResponder, :status => 200

    rescue ActiveRecord::RecordNotFound
      render :json => { :message => ValidationMessages::BAND_INVITATION_NOT_FOUND }, :status => 404 
    end
  end

  def invitation_create
    unless Band.is_member?(params[:id], params[:user_id])
      @invitation = BandInvitation.save(nil,
                                        params[:id],
                                        params[:user_id],
                                        current_user.id,
                                        params[:accepted])
    end
    respond_with @invitation, responder: ApiResponder, :status => 201
    # respond_with @invitation, responder: ApiResponder, :status => 201, :location => api_band_invitation_detail_url(@band, @invitation)
  end

  def invitation_update
    if params[:resend]
      @invitation = BandInvitation.save(params[:invitation_id],
                                        nil,
                                        nil,
                                        nil,
                                        false,
                                        true)
    else
      @invitation = BandInvitation.save(params[:invitation_id],
                                        nil,
                                        nil,
                                        nil,
                                        params[:accepted])
    end
  end

  def invitation_destroy
    begin
      @invitation = BandInvitation.find(params[:invitation_id])
      @invitation.delete
      respond_with responder: ApiResponder, :status => 204

    rescue ActiveRecord::RecordNotFound
      render :json => { :message => ValidationMessages::BAND_INVITATION_NOT_FOUND }, :status => 404 
    end
  end

  def update_photo
    original_fpfile = params[:original_fpfile]
    cropped_fpfile = params[:cropped_fpfile]
    cropped_large_fpfile = params[:cropped_large_fpfile]
    crop_selection = params[:crop_selection]

    # public bucket to allow images to be available to public
    @band.update_photo(original_fpfile, cropped_fpfile, cropped_large_fpfile, crop_selection, Rails.application.config.aws_bucket_public)

    if @band.errors.any?
      render :json => { :message => "Unexpected error updating photo."}, :status => :unprocessable_entity
    else
      render :json => {}, :status => :ok
    end
  end

  def delete_photo
    @band.delete_photo(Rails.application.config.aws_bucket_public)

    if @band.errors.any?
      render :json => { :message => "Unexpected error deleting photo."}, :status => :unprocessable_entity
    else
      render :json => {}, :status => :ok
    end
  end

  def generate_filepicker_policy
    # generates a soon-expiring filepicker policy so that a band can only upload to their own folder in their bucket

    handle = params[:handle]

    call = 'pick,convert,store'

    policy = { :expiry => (DateTime.now + 5.minutes).to_i(),
      :call => call
      #:path => 'avatars/' + @band.id + '/.*jpg'
    }

    # if the caller specifies a handle, add it to the hash
    unless handle.nil?
      start = handle.rindex('/') + 1
      policy[:handle] = handle[start..-1]
    end

    policy = Base64.urlsafe_encode64( policy.to_json )
    digest  = OpenSSL::Digest.new('sha256')
    signature = OpenSSL::HMAC.hexdigest(digest, Rails.application.config.fp_secret, policy)

    render :json => { :signature => signature, :policy => policy }, :status => :ok
  end

  #############################################################################
  protected
    # ensures user is a member of the band
    def auth_band_member
      @band = Band.find(params[:id])
      unless @band.users.exists? current_user
        Rails.logger.info("Could not find #{current_user} in #{@band.users.inspect}")
        raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
      end
    end
    def auth_band_admin
      uid = current_user.id
      @band = Band.find(params[:id])
      unless @band.band_musicians.detect { |bm| bm.user_id == uid && bm.admin? }
        Rails.logger.info("Could not find #{current_user} in #{@band.band_musicians.inspect}")
        raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
      end
    end
end
