require 'spec_helper'

describe "Scheduled Music Session API ", :type => :api do

  subject { page }

  before(:each) do
    MusicSession.delete_all
  end

  def login(user)
    post '/sessions', "session[email]" => user.email, "session[password]" => user.password
    rack_mock_session.cookie_jar["remember_token"].should == user.remember_token
  end

  describe "profile page" do
    let(:user) { FactoryGirl.create(:user) }

    # defopts are used to setup default options for the session
    let(:defopts) { { :name => "session name", :description => "session description",
                      :genres => ["classical"], :musician_access => true, :approval_required => false,
                      :fan_chat => true, :fan_access => true,
                      :legal_policy => true, :language => 'eng',
                      :timezone => "UTC,Etc/UTC",
                      :duration => "60",
                      :rsvp_slots => [{proficiency_level: 1, instrument_id: 'other', approve:true}] } }

    before(:all) do
      ActiveMusicSession.delete_all
      MusicSession.delete_all
    end

    it "should create session" do
      login(user)
      post '/api/sessions.json', defopts.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      music_session = JSON.parse(last_response.body)
      music_session[:name] = defopts[:name]
      music_session[:description] = defopts[:description]
      music_session[:musician_access] = defopts[:musician_access]
      music_session[:fan_chat] = defopts[:fan_chat]
      music_session[:fan_access] = defopts[:fan_access]
      music_session[:language] = defopts[:language]
      music_session[:timezone] = defopts[:timezone]
    end

    it "should list scheduled sessions" do
      login(user)

      post '/api/sessions.json', defopts.merge({start: Time.now + 3.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      post '/api/sessions.json', defopts.merge({start: Time.now + 7.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      post '/api/sessions.json', defopts.merge({start: Time.now + 15.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      get '/api/sessions/scheduled.json'
      last_response.status.should eql(200)
      music_sessions = JSON.parse(last_response.body)

      music_sessions.count.should eql(3)
      expect(Time.parse(music_sessions[0]["scheduled_start"]).to_i).to be < Time.parse(music_sessions[1]["scheduled_start"]).to_i
    end

    it "should delete scheduled sessions" do
      user2 = FactoryGirl.create(:user)
      login(user)

      post '/api/sessions.json', defopts.merge({start: Time.now + 3.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      post '/api/sessions.json', defopts.merge({start: Time.now + 5.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      post '/api/sessions.json', defopts.merge({start: Time.now + 7.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      get '/api/sessions/scheduled.json'
      last_response.status.should eql(200)
      music_sessions = JSON.parse(last_response.body)
      music_sessions.count.should eql(3)

      client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "5")
      post "/api/sessions/#{music_sessions[0]["id"]}/participants.json",
           { :client_id => client.client_id, :as_musician => true,
             :tracks => [{"instrument_id" => "electric guitar",
                          "sound" => "mono",
                          'client_track_id' => "client_track_guid"}]
           }.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      delete "/api/sessions/#{music_sessions[0]["id"]}.json"
      last_response.status.should eql(204)

      delete "/api/sessions/#{music_sessions[1]["id"]}.json"
      last_response.status.should eql(204)

      login(user2)
      delete "/api/sessions/#{music_sessions[2]["id"]}.json"
      last_response.status.should eql(403)
      JSON.parse(last_response.body)["message"].should == ValidationMessages::PERMISSION_VALIDATION_ERROR
    end

    it "should update music session" do
      user2 = FactoryGirl.create(:user)
      login(user)

      post '/api/sessions.json', defopts.merge({start: Time.now + 3.hours}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)
      music_session = JSON.parse(last_response.body)

      post "/api/sessions/#{music_session["id"]}.json", {:name => "changed name"}.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)
      changed_session = JSON.parse(last_response.body)
      changed_session["name"].should == "changed name"

      post "/api/sessions/#{music_session["id"]}.json", {:genres => ["fake genres"]}.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(422)
      changed_session = JSON.parse(last_response.body)
      changed_session["errors"].should == {"genre"=>["can't be blank"]}

      login(user2)
      post "/api/sessions/#{music_session["id"]}.json", {:name => "changed name"}.to_json
      last_response.status.should eql(403)
      JSON.parse(last_response.body)["message"].should == ValidationMessages::PERMISSION_VALIDATION_ERROR
    end
  end

  it "Finds a single open session" do
    creator = FactoryGirl.create(:user)
    session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "My Session")
    client = FactoryGirl.create(:connection, :user => creator, :music_session => session)

    user = FactoryGirl.create(:user)
    login(user)

    get '/api/sessions', "CONTENT_TYPE" => "application/json"
    last_response.status.should == 200
    sessions = JSON.parse(last_response.body)
    sessions.length.should == 1
    sessions.first["description"].should == "My Session"
  end

  it "prepare for perf data upload" do
    user = FactoryGirl.create(:user)
    client = FactoryGirl.create(:connection, :user => user)
    music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session")
    msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id)
  
    put "/api/sessions/#{music_session.id}/perf.json?client_id=#{client.client_id}", "CONTENT_TYPE" => "application/json"

    last_response.status.should == 302
    redirect = last_response.headers["Location"]

    put redirect + '.json', "CONTENT_TYPE" => 'application/json'
    last_response.status.should == 200
    body = JSON.parse(last_response.body)
    perf_data_id = body["id"]

    music_session_perf_data = MusicSessionPerfData.find(perf_data_id)
    music_session_perf_data.should_not be_nil
    music_session_perf_data.music_session_user_history.should == MusicSessionUserHistory.find_by_client_id(client.client_id)
  end

  it "rating" do
    user = FactoryGirl.create(:user)
    client = FactoryGirl.create(:connection, :user => user)
    music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session")
    msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id)
    msuh.rating.should be_nil
    login(user)
    post "/api/participant_histories/#{msuh.client_id}/rating.json", { :rating => 1 }.to_json, "CONTENT_TYPE" => "application/json"
    last_response.status.should == 200
    msuh.reload
    msuh.rating.to_i.should == 1
  end

  it "track sync" do
    pending "recording_session_landing broken tests"
    user = FactoryGirl.create(:single_user_session)
    instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
    music_session = FactoryGirl.create(:active_music_session, :creator => user)
    client = FactoryGirl.create(:connection, :user => user, :music_session => music_session)
    track = FactoryGirl.create(:track, :connection => client, :instrument => instrument)

    existing_track = {:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id }
    new_track = {:client_track_id => "client_track_id1", :instrument_id => instrument.id, :sound => 'stereo'}
    # let's add a new track, and leave the existing one alone
    tracks = [existing_track, new_track]
    login(user)

    put "/api/sessions/#{music_session.id}/tracks.json", { :client_id => client.client_id, :tracks => tracks }.to_json, "CONTENT_TYPE" => "application/json"
    last_response.status.should == 204

    get "/api/sessions/#{music_session.id}/tracks.json", "CONTENT_TYPE" => 'application/json'
    last_response.status.should == 200
    tracks = JSON.parse(last_response.body)
    tracks.size.should == 2
    tracks[0]["id"].should == track.id
    tracks[0]["instrument_id"].should == instrument.id
    tracks[0]["sound"].should == "mono"
    tracks[0]["client_track_id"].should == track.client_track_id
    tracks[1]["instrument_id"].should == instrument.id
    tracks[1]["sound"].should == "stereo"
    tracks[1]["client_track_id"].should == "client_track_id1"
  end

  it "allows start/stop recording playback of a claimed recording" do

    user = FactoryGirl.create(:user)
    connection = FactoryGirl.create(:connection, :user => user)
    track = FactoryGirl.create(:track, :connection => connection, :instrument => Instrument.first)
    music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true)
    # music_session.connections << connection
    music_session.save
    connection.join_the_session(music_session, true, nil, user, 10)
    recording = Recording.start(music_session, user)
    recording.stop
    recording.reload
    claimed_recording = recording.claim(user, "name", "description", Genre.first, true)
    recording.reload

    login(user)
    post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/start.json", {}.to_json, "CONTENT_TYPE" => "application/json"

    last_response.status.should == 201
    music_session.reload
    music_session.claimed_recording.should == claimed_recording
    music_session.claimed_recording_initiator.should == user

    post "/api/sessions/#{music_session.id}/claimed_recording/#{claimed_recording.id}/stop.json", {}.to_json, "CONTENT_TYPE" => "application/json"

    last_response.status.should == 201
    music_session.reload
    music_session.claimed_recording.should be_nil
    music_session.claimed_recording_initiator.should be_nil
  end
end




