require 'spec_helper'

describe ApiMusicSessionsController, type: :controller do
  render_views

  let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] }
  let(:user) { FactoryGirl.create(:user, last_jam_locidispid: 1) }
  let(:conn) { FactoryGirl.create(:connection, :user => user, ip_address: '1.1.1.1', locidispid:1, addr:1) }
  let(:other) { FactoryGirl.create(:user, last_jam_locidispid: 2) }
  let(:other_conn) { FactoryGirl.create(:connection, user: other, ip_address: '2.2.2.2', locidispid:2, addr:2) }
  let(:third_user) { FactoryGirl.create(:user) }
  let(:network_score) { 20 }

  before(:each) do
    controller.current_user = user

    ActiveMusicSession.delete_all
    MusicSession.delete_all
    Score.delete_all
    Score.connection.execute('delete from current_network_scores').check
  end

  describe "ams_index" do

    it "no results" do
      get :ams_index, {client_id: conn.client_id}
      response.should be_success
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 0
    end

    it "just self" do
      # create a session with self in it
      ams = FactoryGirl.create(:active_music_session, creator: user)
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      conn.errors.any?.should be false

      get :ams_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should be_nil
    end

    it "someone else with no score with self" do

      #pending "this test works by itself or only others in the same spec but fails when run with some other tests from other specs"

      # create a session with someone else in it, but no score
      ams = FactoryGirl.create(:active_music_session, creator: other)
      other_conn.join_the_session(ams.music_session, true, tracks, user, 10)
      other_conn.errors.any?.should be false

      get :ams_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should be_nil
    end

    it "someone else with a score with a self" do
      # create a session with someone else in it, but no score
      ams = FactoryGirl.create(:active_music_session, creator: other)
      other_conn.join_the_session(ams.music_session, true, tracks, other, 10)
      other_conn.errors.any?.should be false
      Score.createx(conn.locidispid, conn.client_id, conn.addr, other_conn.locidispid, other_conn.client_id, other_conn.addr, network_score, nil, nil, {auserid: user.id, buserid: other.id})

      get :ams_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:active_music_session][:participants]
      json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should == 35 # 5 + 20 + 10
    end

    it "someone else with a score with a self, and another with an approved RSVP" do
      # create a session with someone else in it, but no score
      ams = FactoryGirl.create(:active_music_session, creator: other)
      other_conn.join_the_session(ams.music_session, true, tracks, other, 10)
      other_conn.errors.any?.should be false

      # we need to make sure that third_user, (the RSVP user) has a locidispid matching the searching user
      third_user.last_jam_audio_latency = 10  # RSVP's are an 'offline' search, meaning they use user.last_jam_audio_latency instead of connection.last_jam_audio_latency
      third_user.last_jam_locidispid = conn.locidispid
      third_user.save!
      Score.createx(conn.locidispid, conn.client_id, conn.addr, other_conn.locidispid, other_conn.client_id, other_conn.addr, network_score, nil, nil, {auserid: user.id, buserid: other.id})

      # set up a second RSVP (other than the creators, pointing to the third_user)
      rsvp_slot = FactoryGirl.create(:rsvp_slot, music_session: ams.music_session, instrument: Instrument.find('piano'))
      rsvp_request = FactoryGirl.create(:rsvp_request, user: third_user)
      rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen:true, rsvp_request: rsvp_request, rsvp_slot:rsvp_slot)

      get :ams_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:active_music_session][:participants][0][:user][:full_score].should_not be_nil
      json[:sessions][0][:approved_rsvps].length.should == 2

      if json[:sessions][0][:approved_rsvps][0][:id] == third_user.id
        found_third_user =  json[:sessions][0][:approved_rsvps][0]
        found_creator = json[:sessions][0][:approved_rsvps][1]
        found_creator[:id].should == other.id
      else
        found_third_user =  json[:sessions][0][:approved_rsvps][1]
        found_creator = json[:sessions][0][:approved_rsvps][0]
        found_third_user[:id].should == third_user.id
        found_creator[:id].should == other.id
      end

      found_third_user[:full_score].should == nil
      found_creator[:full_score].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency )).ceil
    end
  end


  describe "sms_index" do

    it "no results" do
      get :sms_index, {client_id: conn.client_id}
      response.should be_success
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 0
    end

    it "just self" do
      # create a session with self in it
      sms = FactoryGirl.create(:music_session, creator: user)

      get :sms_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:approved_rsvps][0][:id].should == user.id
      json[:sessions][0][:approved_rsvps][0][:full_score].should be_nil # you don't get scores to self
    end

    it "someone else with no score with self" do

      #pending "this test works by itself or only others in the same spec but fails when run with some other tests from other specs"

      # create a session with someone else in it, but no score
      sms = FactoryGirl.create(:music_session, creator: other)

      get :sms_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:approved_rsvps][0][:id].should == other.id
      json[:sessions][0][:approved_rsvps][0][:full_score].should be_nil # there is no score with 'other '
    end

    it "scores with invitees and RSVP's" do
      # create a session with someone else in it, but no score
      sms = FactoryGirl.create(:music_session, creator: other)
      Score.createx(conn.locidispid, conn.client_id, conn.addr, other_conn.locidispid, other_conn.client_id, other_conn.addr, network_score, nil, nil, {auserid: user.id, buserid: other.id})

      invitee = FactoryGirl.create(:user, last_jam_audio_latency: 30, last_jam_locidispid: 3)
      FactoryGirl.create(:friendship, user: other, friend: invitee)
      FactoryGirl.create(:friendship, user: invitee, friend: other)
      FactoryGirl.create(:invitation, sender:other, receiver:invitee, music_session: sms)

      Score.createx(invitee.last_jam_locidispid, 'immaterial', 1, conn.locidispid, conn.client_id, conn.addr, network_score, nil, nil, {auserid: invitee.id, buserid: user.id})

      get :sms_index, {client_id: conn.client_id}
      json = JSON.parse(response.body, :symbolize_names => true)
      json[:sessions].length.should == 1
      json[:sessions][0][:approved_rsvps][0][:id].should == other.id
      json[:sessions][0][:approved_rsvps][0][:full_score].should == ((network_score + user.last_jam_audio_latency + other.last_jam_audio_latency)).ceil
      json[:sessions][0][:invitations][0][:receiver_id].should == invitee.id
      json[:sessions][0][:invitations][0][:full_score].should == nil
    end

  end

  describe "open_jam_track" do

    let(:ams) { FactoryGirl.create(:active_music_session, creator: user) }
    let(:jam_track) { FactoryGirl.create(:jam_track)}

    it "does not allow someone to open a track unless they are in the session" do
      post :jam_track_open, {:format => 'json', id: ams.id, jam_track_id: jam_track.id}
      response.status.should == 403
    end

    it "does not allow someone to open a track unless they own the jam track" do
      conn.join_the_session(ams.music_session, true, tracks, user, 10)

      post :jam_track_open, {:format => 'json', id: ams.id, jam_track_id: jam_track.id}
      response.status.should == 403
    end

    it "allows someone who owns the jam track to open it" do
      # put the connection of the user into the session, so th
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      FactoryGirl.create(:jam_track_right, jam_track: jam_track, user: user)

      post :jam_track_open, {:format => 'json', id: ams.id, jam_track_id: jam_track.id}
      response.status.should == 200
    end

    it "does not allow someone to close a track unless they are in the session" do
      post :jam_track_close, {:format => 'json', id: ams.id}
      response.status.should == 403
    end

    it "allows the jam track to be closed" do
      # put the connection of the user into the session, so th
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      FactoryGirl.create(:jam_track_right, jam_track: jam_track, user: user)

      post :jam_track_open, {:format => 'json', id: ams.id, jam_track_id: jam_track.id}
      response.status.should == 200

      post :jam_track_close, {:format => 'json', id: ams.id}
      response.status.should == 200
    end

    it "show.rabl shows jam track info when open" do
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      FactoryGirl.create(:jam_track_right, jam_track: jam_track, user: user)
      post :jam_track_open, {:format => 'json', id: ams.id, jam_track_id: jam_track.id}

      # check the show.rabl for jam_track info
      get :show, {:format => 'json', id: ams.id}
      json = JSON.parse(response.body, :symbolize_names => true)

      json[:jam_track].should_not be_nil
      json[:jam_track][:id].should == jam_track.id
    end
  end

  describe "open_backing_track" do

    let(:ams) { FactoryGirl.create(:active_music_session, creator: user) }
    let(:backing_track) { "foo.mp3"}

    it "does not allow someone to open a track unless they are in the session" do
      post :backing_track_open, {:format => 'json', id: ams.id, backing_track_path: backing_track}
      response.status.should == 403
    end

    it "does not allow someone to open a track unless they own the backing track" do
      pending "connection with client to determine ownership"
      conn.join_the_session(ams.music_session, true, tracks, user, 10)

      post :backing_track_open, {:format => 'json', id: ams.id, backing_track_path: backing_track}
      response.status.should == 403
    end

    it "allows someone who owns the backing track to open it" do
      # put the connection of the user into the session, so th
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      
      post :backing_track_open, {:format => 'json', id: ams.id, backing_track_path: backing_track}
      response.status.should == 200
    end

    it "does not allow someone to close a track unless they are in the session" do
      post :backing_track_close, {:format => 'json', id: ams.id}
      response.status.should == 403
    end

    it "allows the backing track to be closed" do
      # put the connection of the user into the session, so th
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      
      post :backing_track_open, {:format => 'json', id: ams.id, backing_track_path: backing_track}
      response.status.should == 200

      post :backing_track_close, {:format => 'json', id: ams.id}
      response.status.should == 200
    end
  end

  describe "open_metronome" do

    let(:ams) { FactoryGirl.create(:active_music_session, creator: user) }
    let(:metronome) { "foo.mp3"}

    it "does not allow someone to open a track unless they are in the session" do
      post :metronome_open, {:format => 'json', id: ams.id, metronome_path: metronome}
      response.status.should == 403
    end

    it "can open it" do
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      
      post :metronome_open, {:format => 'json', id: ams.id, metronome_path: metronome}
      response.status.should == 200
    end

    it "does not allow someone to close a metronome" do
      post :metronome_close, {:format => 'json', id: ams.id}
      response.status.should == 403
    end

    it "does allow someone who joied to close a metronome" do
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      post :metronome_close, {:format => 'json', id: ams.id}
      response.status.should == 200
    end

    it "allows the metronome to be closed" do
      # put the connection of the user into the session, so th
      conn.join_the_session(ams.music_session, true, tracks, user, 10)
      
      post :metronome_open, {:format => 'json', id: ams.id, metronome_path: metronome}
      response.status.should == 200

      post :metronome_close, {:format => 'json', id: ams.id}
      response.status.should == 200
    end
  end
end
