require 'aws-sdk'

class ApiMusicSessionsController < ApiController

  # have to be signed in currently to see this screen
  before_filter :api_signed_in_user, :except => [ :add_like, :show, :show_history, :add_session_info_comment ]
  before_filter :lookup_session,   only: [:show, :update, :delete, :claimed_recording_start, :claimed_recording_stop, :track_sync, :jam_track_open, :jam_track_close, :backing_track_open, :backing_track_close, :metronome_open, :metronome_close, :attach_recording]
  before_filter :lookup_perm_session,   only: [:get_livestream, :create_livestream, :livestream_transition]
  skip_before_filter :api_signed_in_user, only: [:perf_upload]
  around_filter :transactions_filter, only:[:sms_index, :ams_index]

  respond_to :json

  def index
    # returns a list of sessions which are hopefully interesting to you as three buckets (concatenated). The 1st bucket
    # is those session to which you've been invited. The 2nd bucket is those sessions which are about a band that you
    # are in or in which a friend is participating. The 3rd bucket is everything else (sessions - invites - friends - bands).
    # params[:participants] is either nil, meaning "everything", or it's an array of musician ids
    # params[:genres] is either nil, meaning "everything", or it's an array of genre ids
    # params[:friends_only] does the obvious. you get invited and friends sessions only.
    # params[:my_bands_only] also does the obvious. you get invited and bands sessions only.
    # params[:keyword] matches only sessions with that text in the description
    # params[:as_musician] only returns sessions you can join as a musician (if true) or listen to a fan (if false)
    # Importantly, friends_only and my_bands_only are ORed not ANDed. So, if you specify both as true, you'll get more
    # results than if only one or the other is true, not fewer. if either is true you won't see the "everything else"
    # sessions.
    @music_sessions = ActiveMusicSession.index(current_user,
                                         participants: params[:participants],
                                         genres: params[:genres],
                                         friends_only: params[:friends_only],
                                         my_bands_only: params[:my_bands_only],
                                         keyword: params[:keyword],
                                         as_musician: params[:as_musician])
  end

  def nindex
    # returns a list of sessions which are hopefully interesting to you as three buckets (concatenated). The 1st bucket
    # is those session to which you've been invited. The 2nd bucket is those sessions which are about a band that you
    # are in or in which a friend is participating. The 3rd bucket is everything else (sessions - invites - friends - bands).
    # pretty much the same as #index above, except scores are also returned.
    # params[:client_id] is the client_id of the client making the call. needed to resovle scoring.
    # params[:participants] is either nil, meaning "everything", or it's an array of musician ids
    # params[:genres] is either nil, meaning "everything", or it's an array of genre ids
    # params[:friends_only] does the obvious. you get invited and friends sessions only.
    # params[:my_bands_only] also does the obvious. you get invited and bands sessions only.
    # params[:keyword] matches only sessions with that text in the description
    # params[:as_musician] only returns sessions you can join as a musician (if true) or listen to a fan (if false)
    # params[:offset] also does the obvious, starts at offset in the results (e.g. 0)
    # params[:limit] also does the obvious, limits number of rows returned (e.g. 20)
    # Importantly, friends_only and my_bands_only are ORed not ANDed. So, if you specify both as true, you'll get more
    # results than if only one or the other is true, not fewer. if either is true you won't see the "everything else"
    # sessions.
    @music_sessions = ActiveMusicSession.nindex(current_user,
                                         client_id: params[:client_id],
                                         participants: params[:participants],
                                         genres: params[:genres],
                                         friends_only: params[:friends_only],
                                         my_bands_only: params[:my_bands_only],
                                         keyword: params[:keyword],
                                         as_musician: params[:as_musician],
                                         offset: params[:offset],
                                         limit: params[:limit])
  end

  def friend_active_index
    @music_sessions = ActiveMusicSession.friend_active_index(current_user, params)
  end

  def public_index
    @music_sessions = ActiveMusicSession.public_index(current_user, params)
  end

  def ams_index
    # returns a relation which will produce a list of music_sessions which are active and augmented with attributes
    # tag and latency, then sorted by tag, latency, and finally music_sessions.id (for stability). the list is
    # filtered by genre, lang, and keyword, then paged by offset and limit (those are record numbers not page numbers).
    # tag is 1 for chosen rsvp'd sessions, 2 for invited sessions, 3 for all others (musician_access).
    # TODO: if you're the creator of a session it will be treated the same as if you had rsvp'd and been accepted.
    ActiveRecord::Base.transaction do
      @music_sessions, @user_scores = ActiveMusicSession.ams_index(current_user, params)
    end
  end

  def sms_index
    # returns a relation which will produce a list of music_sessions which are scheduled and augmented with attributes
    # tag and latency, then sorted by tag, latency, and finally music_sessions.id (for stability). the list is
    # filtered by genre, lang, and keyword, then paged by offset and limit (those are record numbers not page numbers).
    # tag is 1 for chosen rsvp'd sessions, 2 for invited sessions, 3 for all others (musician_access).
    # TODO: if you're the creator of a session it will be treated the same as if you had rsvp'd and been accepted.
    ActiveRecord::Base.transaction do
      @music_sessions, @user_scores = MusicSession.sms_index(current_user, params)
      return
    end
  end

  def sms_index_2
      @music_sessions = MusicSession.scheduled_index(current_user, params)
      @user_scores = {}
  end

  def scheduled
    @music_sessions = MusicSession.scheduled(current_user)
  end

  def scheduled_rsvp
    @music_sessions = MusicSession.scheduled_rsvp(current_user)
  end

  def create
    @music_session = MusicSession.create(current_user, params)

    if @music_session.errors.any?
      response.status = :unprocessable_entity
      respond_with @music_session
    else
      respond_with @music_session, responder: ApiResponder
    end
  end

  def create_legacy
    client_id = params[:client_id]

    if client_id.nil?
      raise JamArgumentError, "client_id must be specified"
    end

    unless params[:intellectual_property]
      raise JamArgumentError, "You must agree to the intellectual property terms"
    end

    band = Band.find(params[:band]) unless params[:band].nil?

    # creating the MusicSession right here was added as part of the scheduled sessions changes
    # Why? The new order of things is to always have a MusicSession before a ActiveMusicSession
    # So, we have to make MusicSession, and pass in it's .id to MusicSessionManager.new.create()
    # so that the ActiveMusicSession can have the same .id as the MusicSession
    history = MusicSession.new
    history.name = params[:description][0..40]
    history.description = params[:description]
    history.musician_access = params[:musician_access]
    history.approval_required = params[:approval_required]
    history.fan_chat = params[:fan_chat]
    history.fan_access = params[:fan_access]
    history.band = band
    history.genre_id = (params[:genres].length > 0 ? params[:genres][0] : nil) if params[:genres]
    history.legal_terms = params[:legal_terms]
    history.language = 'eng'
    history.legal_policy = 'standard'
    history.creator = current_user
    history.school_id = current_user.school_id
    history.is_platform_instructor = current_user.is_platform_instructor
    history.save

    if history.errors.any?
      @music_session = history
      response.status = :unprocessable_entity
      respond_with @music_session
    else
      history.reload # to get .id back
      @music_session = MusicSessionManager.new.create(
          history,
          current_user,
          client_id,
          params[:description],
          params[:musician_access],
          params[:approval_required],
          params[:fan_chat],
          params[:fan_access],
          band,
          params[:genres],
          params[:tracks],
          params[:legal_terms],
          params[:audio_latency])

      if @music_session.errors.any?
        response.status = :unprocessable_entity
        respond_with @music_session
      else
        respond_with @music_session, responder: ApiResponder, :location => api_session_detail_url(@music_session)
      end
    end
  end

  def show
    unless @music_session.can_see? current_user
      # render :json => { :message => ValidationMessages::PERMISSION_VALIDATION_ERROR }, :status => 403
      raise JamRuby::JamPermissionError
    end
  end

  def update
    @music_session = MusicSessionManager.new.update(current_user,
      @music_session.music_session,
      params[:name],
      params[:description],
      params[:genre] ? Genre.find(params[:genre]) : nil,
      params[:language],
      params[:musician_access],
      params[:approval_required],
      params[:fan_chat],
      params[:fan_access],
      params[:session_controller],
      params[:friends_can_join])

    if @music_session.errors.any?
      # we have to do this because api_session_detail_url will fail with a bad @music_session
      response.status = :unprocessable_entity
      respond_with @music_session
    else
      @music_session = @music_session.active_music_session
      respond_with_model(@music_session)
    end
  end

  def attach_recording

    me = current_user

    recordings = params[:recordings]
    recordings.each do |recording_data|
      #recording = Recording.find(recording_data[:id])
      claimed_recording = ClaimedRecording.find_by_id(recording_data[:id])
      if claimed_recording.nil? || claimed_recording.user != current_user
        raise JamPermissionError, 'only owner of claimed_recording can associated it with a lesson'
      end

      msg = ChatMessage.create(me, @music_session, '', ChatMessage::CHANNEL_SESSION, nil, nil, nil, 'JamKazam Recording', nil, claimed_recording)
    end

    render :json => {}, :status => 200

  end

  def session_update
    begin
      @music_session = MusicSession.find(params[:id])
      if @music_session.creator == current_user

        @music_session.name = params[:name] if params.include? :name
        @music_session.description = params[:description] if params.include? :description
        @music_session.musician_access = params[:musician_access] if params.include? :musician_access
        @music_session.approval_required = params[:approval_required] if params.include? :approval_required
        @music_session.fan_chat = params[:fan_chat] if params.include? :fan_chat
        @music_session.fan_access = params[:fan_access] if params.include? :fan_access
        @music_session.friends_can_join = params[:friends_can_join] if params.include? :friends_can_join
        @music_session.genre = Genre.find_by_id(params[:genres][0]) if params.include?(:genres) && params[:genres] && params[:genres].length > 0
        @music_session.legal_policy = params[:legal_policy] if params.include? :legal_policy
        @music_session.language = params[:language] if params.include? :language
        @music_session.scheduled_start = MusicSession.parse_scheduled_start(params[:start], params[:timezone]) if params.include?(:start) && params.include?(:timezone)
        @music_session.scheduled_duration = params[:duration] + ' minutes' if params.include? :duration
        @music_session.timezone = params[:timezone] if params.include? :timezone
        @music_session.recurring_mode = params[:reoccurrence] if params.include? :reoccurrence
        @music_session.open_rsvps = params[:open_rsvps] if params.include? :open_rsvps
        @music_session.band =  (params[:band] ? Band.find(params[:band]) : nil) if params.include? :band
        @music_session.save

        if params.include? :music_notations
          notations = JSON.parse(params[:music_notations])
          notations.each do |n|
            notation = MusicNotation.find(n["id"])
            notation.music_session = @music_session
            notation.save

            @music_session.music_notations << notation
          end
        end

        if @music_session.errors.any?
          response.status = :unprocessable_entity
          respond_with @music_session
        else
          Notification.send_scheduled_session_rescheduled(@music_session) if @music_session.scheduling_info_changed

          respond_with @music_session, responder: ApiResponder, :location => api_session_history_detail_url(@music_session)
        end
      else
        render :json => { :message => ValidationMessages::PERMISSION_VALIDATION_ERROR }, :status => 403
      end

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

  def destroy
    begin
      music_session = MusicSession.find(params[:id])
      if music_session.can_cancel? current_user
        Notification.send_scheduled_session_cancelled music_session
        music_session.canceled = true
        music_session.save
        respond_with responder: ApiResponder, :status => 204
      else
        render :json => { :message => ValidationMessages::PERMISSION_VALIDATION_ERROR }, :status => 403
      end

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

  def participant_show
    @connection = Connection.find_by_client_id(params[:id])
  end

  def participant_create_legacy
    @connection = MusicSessionManager.new.participant_create(
      current_user,
      params[:id],
      params[:client_id],
      params[:as_musician],
      params[:tracks],
      params[:audio_latency])

    if @connection.errors.any?
      response.status = :unprocessable_entity
      respond_with @connection
    else
      respond_with @connection, responder: ApiResponder, :location => api_session_participant_detail_url(@connection.client_id)
    end
  end

  def participant_create
    client_id = params[:client_id]

    if client_id.nil?
      raise JamArgumentError, "client_id must be specified"
    end

    begin
      @subscription_rules = current_user.subscription_rules
      @music_session = ActiveMusicSession.find_by_id(params[:id])
      if @music_session && @music_session.users.count >= 1
        if @music_session.users.count == 1 && @music_session.users.first.id == current_user.id
          # if somehow we find ourselves in the session, just ignore that case.
        else
          @session_rules = { remaining_session_play_time: @music_session.play_time_remaining(current_user) }

          # check if the user has gone past acceptable play time
          if !@session_rules[:remaining_session_play_time].nil? && @session_rules[:remaining_session_play_time] <= 0
            # user has no session time for this session left.
            render :json => { :errors => {:remaining_session_play_time => ['none remaining']}}, :status => 422
            return
          elsif !@subscription_rules[:remaining_month_play_time].nil? && @subscription_rules[:remaining_month_play_time] <= 0
            # user has no session time this month.
            render :json => { :errors => {:remaining_month_play_time=> ['none remaining']}}, :status => 422
            return
          end
        end

      end

      @connection = ActiveMusicSession.participant_create(
          current_user,
          params[:id],
          params[:client_id],
          params[:as_musician],
          params[:tracks],
          params[:audio_latency],
          params[:client_role],
          params[:parent_client_id]
      )


      if @connection.errors.any?
        response.status = :unprocessable_entity
        respond_with @connection
      else
        @music_session = @connection.music_session
        if @session_rules.nil?
          @session_rules = { remaining_session_play_time: @music_session.play_time_remaining(current_user) }
        end

        # used in rabl to render extra data
        @on_join = true
        respond_with @music_session, responder: ApiResponder, :status => 201, :location => api_session_detail_url(@connection.music_session)
      end

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

  def participant_delete
    client_id = params[:id]
    if client_id.present? && client_id != 'undefined'
      @connection = Connection.find_by_client_id!(client_id)
      active_music_session = ActiveMusicSession.find(@connection.music_session_id)
      MusicSessionManager.new.participant_delete(current_user, @connection, active_music_session)
    end
    respond_with @connection, responder: ApiResponder
  end

  def participant_rating
    if @history = MusicSessionUserHistory.latest_history(params[:client_id])
      if request.post?
        rating = params[:rating].to_i
        rating_val = params[:rating]
        comment = params[:comment]
        backend_details = params[:backend_details]

        @history.add_rating(rating, comment, backend_details)
        @history.save

        if @history.errors.any?
          response.status = :unprocessable_entity
          respond_with @history
          return
        else
          if @history.good_rating? && @history.user.first_good_music_session_at.nil?
            @history.user.first_good_music_session_at = Time.now
            @history.user.save
          end
        end


        begin

          lesson_link = nil
          session_link = @history.music_session.admin_url
          if @history.music_session.lesson_session
            session_type = "Lesson"
            lesson_link = @history.music_session.lesson_session.admin_url
          else
            session_type = "Session"
          end

          rating_type = rating > 0 ? "Good" : "Bad"
          with_comment = (comment.nil? || comment.strip.empty?) ? '' : ' - With Comment'
          subject = "#{current_user.name} Rated Their #{session_type} #{rating_type}#{with_comment}!"
          body = "Session Type: #{session_type}\n"
          body << "Session Rating: #{rating_type}\n"
          body << "Session Rating Arg: #{rating_val}\n"
          body << "User: #{current_user.email}\n"
          body << "Music Session URL: #{session_link}\n"
          if lesson_link
            body << "Lesson URL: #{lesson_link}\n"
          end
          body << "Session Comments: #{comment}\n"

          if backend_details
            begin
            body << "Backend Detail:\n" + JSON.pretty_generate(backend_details) + "\n"
            rescue Exception => e
              puts "Unable to send out retails ratings due to bad backend data #{e}"
              logger.error("Unable to send out retails ratings due to bad backend data #{e}")
            end
          else
            body << "Backend Detail: NONE in POST!!\n"
          end

          backend_details["rating_type"] = rating_type
          backend_details["comment"] = comment
          succeeded = JamRuby::ElasticSearch.new.session_ratings(@history.music_session, current_user, backend_details)

          body << (succeeded ? "Stored in ElasticSearch" : "Unable to store in ElasticSearch!")
          AdminMailer.jamclass_alerts({subject: subject, body: body}).deliver_now
        rescue Exception => e
          puts "Exception sending out ratings email. Boo #{e}"
          logger.error("Exception sending out ratings email. Boo #{e}")
        end
        render :json => {}, :status => :ok


      elsif request.get?
        render :json => { :should_rate_session => @history.should_rate_session? }, :status => :ok
      end
    else
      render :json => { :message => ValidationMessages::SESSION_NOT_FOUND }, :status => 404
    end
  end

  def track_index
    @tracks = Track.index(current_user, params[:id])
  end

  def track_show
    begin
      @track = Track.joins(:connection)
                    .where(:connections => {:user_id => "#{current_user.id}"})
                    .find(params[:track_id])

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

  def track_sync
    @tracks = MusicSessionManager.new.sync_tracks(@music_session, params[:client_id], params[:tracks], params[:backing_tracks], params[:metronome_open])

    unless @tracks.kind_of? Array
      # we have to do this because api_session_detail_url will fail with a bad @tracks
      response.status = :unprocessable_entity
      respond_with @tracks
    else
      respond_with @tracks, responder: ApiResponder
    end
  end

  def track_create
    @track = Track.save(nil,
                        params[:connection_id],
                        params[:instrument_id],
                        params[:sound],
                        params[:client_track_id],
                        params[:client_resource_id])

    respond_with @track, responder: ApiResponder, :status => 201, :location => api_session_track_detail_url(@track.connection.music_session, @track)
  end

  def track_update
    begin
      @track = Track.save(params[:track_id],
                          nil,
                          params[:instrument_id],
                          params[:sound],
                          params[:client_track_id],
                          params[:client_resource_id])
      
      respond_with @track, responder: ApiResponder, :status => 200

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

  def track_destroy
    begin
      @track = Track.find(params[:track_id])
      unless @track.nil?
        @track.delete
        respond_with responder: ApiResponder, :status => 204
      end
    rescue ActiveRecord::RecordNotFound
      render :json => { :message => ValidationMessages::TRACK_NOT_FOUND }, :status => 404 
    end
  end

  def perf_upload
    # example of using curl to access this API:
    # curl -L -T some_file -X PUT http://localhost:3000/api/sessions/[SESSION_ID]/perf.json?client_id=[CLIENT_ID]

    music_session = MusicSession.find(params[:id])
    msuh = MusicSessionUserHistory.find_by_client_id(params[:client_id])

      @perfdata = MusicSessionPerfData.new
    @perfdata.client_id = params[:client_id]
    @perfdata.music_session = music_session
    unless @perfdata.save
      # we have to do this because api_session_detail_url will fail with a bad @music_session
      response.status = :unprocessable_entity
      respond_with @perfdata
      return
    end

    if Rails.application.config.storage_type == :fog
      uri = @perfdata.uri
      s3 = AWS::S3.new(:access_key_id => Rails.application.config.aws_access_key_id,
                       :secret_access_key => Rails.application.config.aws_secret_access_key)
      bucket = s3.buckets[SampleApp::Application.config.aws_bucket]

      expire = Time.now + 20.years
      read_url = bucket.objects[uri].url_for(:read, 
                                             :expires => expire, 
                                             :'response_content_type' => 'text/csv').to_s
      @perfdata.update_attribute(:uri, read_url)
      logger.debug("*** client can read url #{read_url}")

      write_url = bucket.objects[uri].url_for(:write, 
                                              :expires => expire, 
                                              :'response_content_type' => 'text/csv').to_s
      logger.debug("*** client can upload to url #{write_url}")
      redirect_to write_url

    else
      if params[:redirected_back].nil? || !params[:redirected_back]
        # first time that a client has asked to do a PUT (not redirected back here)
        redirect_to request.fullpath + '&redirected_back=true'
      else
        # we should store it here to aid in development, but we don't have to until someone wants the feature
        # so... just return 200
        render :json => { :id => @perfdata.id }, :status => 200
      end
    end
  end

  def add_comment
    if params[:id].blank?
      render :json => { :message => "Session ID is required" }, :status => 400
      return
    end

    if params[:user_id].blank?
      render :json => { :message => "User ID is required" }, :status => 400
      return
    end

    if params[:comment].blank?
      render :json => { :message => "Comment is required" }, :status => 400
      return
    end

    comment = MusicSessionComment.new
    comment.music_session_id = params[:id]
    comment.creator_id = params[:user_id]
    comment.comment = @@html_encoder.encode(params[:comment])
    comment.ip_address = request.remote_ip
    comment.save

    if comment.errors.any?
      render :json => { :errors => comment.errors }, :status => 422
      return
    else
      render :json => {}, :status => 201
      return
    end
  end

   def add_session_info_comment
    if params[:id].blank?
      render :json => { :message => "Session ID is required" }, :status => 400
      return
    end

    if params[:comment].blank?
      render :json => { :message => "Comment is required" }, :status => 400
      return
    end

    comment = SessionInfoComment.new
    comment.music_session_id = params[:id]
    comment.creator_id = current_user.id
    comment.comment = @@html_encoder.encode(params[:comment])
    comment.save

    if comment.errors.any?
      render :json => { :errors => comment.errors }, :status => 422
      return
    else
      music_session = MusicSession.find(params[:id])
      Notification.send_scheduled_session_comment(music_session, current_user, params[:comment])
      render :json => {}, :status => 201
      return
    end
  end

  def add_like
    if params[:id].blank?
      render :json => { :message => "Session ID is required" }, :status => 400
      return
    end

    liker = MusicSessionLiker.new
    liker.music_session_id = params[:id]
    liker.liker_id = params[:user_id]
    liker.ip_address = request.remote_ip
    liker.save

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

  def show_history
    if current_user
      ActiveRecord::Base.transaction do
        @history, @user_scores = MusicSession.session_with_scores(current_user, params[:id], params[:includePending])
      end
    else
      @history = MusicSession.find(params[:id])
    end
  end

  def claimed_recording_start
    @music_session.claimed_recording_start(current_user, ClaimedRecording.find(params[:claimed_recording_id]))

    if @music_session.errors.any?
      # we have to do this because api_session_detail_url will fail with a bad @music_session
      response.status = :unprocessable_entity
      respond_with @music_session
    else
      respond_with @music_session, responder: ApiResponder
    end
  end

  def claimed_recording_stop
    @music_session.claimed_recording_stop

    if @music_session.errors.any?
      # we have to do this because api_session_detail_url will fail with a bad @music_session
      response.status = :unprocessable_entity
      respond_with @music_session
    else
      respond_with @music_session, responder: ApiResponder
    end
  end

  def jam_track_open
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

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

    jam_track_right = @jam_track.right_for_user(current_user)

    unless jam_track_right
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    if jam_track_right.redeemed == true && current_user.email_needs_verification
      raise JamPermissionError, ValidationMessages::VERIFY_EMAIL
    end

    @music_session.open_jam_track(current_user, @jam_track)

    respond_with_model(@music_session)
  end

  def jam_track_close
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @music_session.close_jam_track

    respond_with_model(@music_session)
  end

  def backing_track_open
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @backing_track_path = params[:backing_track_path]    
    @music_session.open_backing_track(current_user, @backing_track_path)
    respond_with_model(@music_session)
  end

  def backing_track_close
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @music_session.close_backing_track()
    respond_with_model(@music_session)
  end

  def metronome_open
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @music_session.open_metronome(current_user)
    respond_with_model(@music_session)
  end

  def metronome_close
    unless @music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @music_session.close_metronome()
    respond_with_model(@music_session)
  end

  def get_livestream
    unless @music_session.active_music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @livestream = @music_session.get_broadcast(current_user)

    if @livestream
      @music_session.refresh_stream(current_user, @livestream)
      respond_with (@livestream), responder: ApiResponder
    else
      render :json => { :message => "No broadcast associated with this session" }, :status => 404
    end
  end

  def create_livestream
    unless @music_session.active_music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    @livestream = @music_session.create_stream(current_user, params[:options])
    respond_with (@livestream), responder: ApiResponder
  end

  def livestream_transition
    unless @music_session.active_music_session.users.exists?(current_user.id)
      raise JamPermissionError, ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    broadcast = @music_session.get_broadcast(current_user)

    if broadcast
      @livestream = @music_session.transition_broadcast(current_user, broadcast, params[:broadcastStatus])
      respond_with (@livestream), responder: ApiResponder
    else
      render :json => { :message => "No broadcast associated with this session" }, :status => 404
    end
  end

  private

  def lookup_session
    @music_session = ActiveMusicSession.find(params[:id])
  end

  def lookup_perm_session
    @music_session = MusicSession.find(params[:id])
  end
end
