require 'spec_helper'

describe ActiveMusicSession do

  TRACKS = [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "some_client_track_id"}]

  before(:each) do
    ActiveMusicSession.delete_all
    IcecastServer.delete_all
    IcecastMount.delete_all
  end

  describe "participant_create" do

    let(:user) { FactoryGirl.create(:user) }

    it "fails gracefully when no connection" do
      music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)

      begin
        ActiveMusicSession.participant_create(user, music_session.id, "junk", true, nil, 5)
        false.should be_true
      rescue JamRuby::JamRecordNotFound => e
        e.record_type.should eql "Connection"
        e.missing_message.should eql "Unable to find connection by client_id junk"
      end

    end

    it "succeeds no active music session" do
      music_session = FactoryGirl.create(:music_session, :creator => user, :musician_access => false)
      conn = FactoryGirl.create(:connection, :user => user)
      connection = ActiveMusicSession.participant_create(user, music_session.id, conn.client_id, true, nil, 5)
      connection.errors.any?.should be false
      ActiveMusicSession.find(music_session.id)
    end

    it "fails gracefully when invalid music session Id" do
      music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)
      conn = FactoryGirl.create(:connection, :user => user)
      expect { ActiveMusicSession.participant_create(user, 'bad music session ID', conn.client_id, true, nil, 5) }.to raise_error(ActiveRecord::RecordNotFound)
    end

    it "pulls out of other session" do
      music_session1 = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)
      music_session2 = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)
      conn = FactoryGirl.create(:connection, :user => user, music_session: music_session2)
      connection = ActiveMusicSession.participant_create(user, music_session1.id, conn.client_id, true, nil, 5)
      connection.should eql conn
      connection.errors.any?.should be true
    end

    it "user-less connection bails appropriately" do
      music_session1 = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)
      conn = FactoryGirl.create(:connection)
      ActiveRecord::Base.connection.execute("update connections set user_id = NULL where connections.id = '#{conn.id}'")
      expect { ActiveMusicSession.participant_create(user, music_session1.id, conn.client_id, true, nil, 5) }.to raise_error(JamRuby::JamPermissionError)
    end
  end

  it 'can grant access to valid user' do

    user1 = FactoryGirl.create(:user) # in the jam session
    user2 = FactoryGirl.create(:user) # in the jam session
    user3 = FactoryGirl.create(:user) # not in the jam session

    music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false)
    FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
    FactoryGirl.create(:connection, :user => user2, :music_session => music_session)


    music_session.access?(user1).should == true
    music_session.access?(user2).should == true
    music_session.access?(user3).should == false
  end

  it 'anyone can join a open music session' do

    user1 = FactoryGirl.create(:user) # in the jam session
    user2 = FactoryGirl.create(:user) # in the jam session
    user3 = FactoryGirl.create(:user) # not in the jam session

    music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true)

    music_session.can_join?(user1, true).should == true
    music_session.can_join?(user2, true).should == true
    music_session.can_join?(user3, true).should == true
  end

  it 'no one but invited people can join closed music session' do
    user1 = FactoryGirl.create(:user) # in the jam session
    user2 = FactoryGirl.create(:user) # in the jam session
    user3 = FactoryGirl.create(:user) # not in the jam session

    music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false)
    FactoryGirl.create(:connection, :user => user1, :music_session => music_session)

    music_session.can_join?(user1, true).should == true
    music_session.can_join?(user2, true).should == false
    music_session.can_join?(user3, true).should == false

    # invite user 2
    FactoryGirl.create(:friendship, :user => user1, :friend => user2)
    FactoryGirl.create(:friendship, :user => user2, :friend => user1)
    FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session)

    music_session.can_join?(user1, true).should == true
    music_session.can_join?(user2, true).should == true
    music_session.can_join?(user3, true).should == false
  end

  it 'no one but invited people can see closed music session' do
    user1 = FactoryGirl.create(:user) # in the jam session
    user2 = FactoryGirl.create(:user) # in the jam session
    user3 = FactoryGirl.create(:user) # not in the jam session

    music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => false, :fan_access => false)
    FactoryGirl.create(:connection, :user => user1, :music_session => music_session)

    music_session.can_see?(user1).should == true
    music_session.can_see?(user2).should == false
    music_session.can_see?(user3).should == false

    # invite user 2
    FactoryGirl.create(:friendship, :user => user1, :friend => user2)
    FactoryGirl.create(:friendship, :user => user2, :friend => user1)
    FactoryGirl.create(:invitation, :sender => user1, :receiver => user2, :music_session => music_session.music_session)

    music_session.can_see?(user1).should == true
    music_session.can_see?(user2).should == true
    music_session.can_see?(user3).should == false
  end

  describe "index" do
    it "orders two sessions by created_at starting with most recent" do
      creator = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)

      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
      FactoryGirl.create(:connection, :user => creator, :music_session => earlier_session)

      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)

      user = FactoryGirl.create(:user)

      #ActiveRecord::Base.logger = Logger.new(STDOUT)
      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 2
      music_sessions.first.id.should == later_session.id
    end

    it "orders sessions with inviteds first, even if created first" do
      creator1 = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)

      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session")
      FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)
      user = FactoryGirl.create(:user)
      FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
      FactoryGirl.create(:friendship, :user => creator1, :friend => user)
      FactoryGirl.create(:friendship, :user => user, :friend => creator1)
      FactoryGirl.create(:invitation, :sender => creator1, :receiver => user, :music_session => earlier_session.music_session)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 2
      music_sessions.first.id.should == earlier_session.id
    end


    it "orders sessions with friends in the session first, even if created first" do

      creator1 = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)
      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator1, :description => "Earlier Session")
      FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      FactoryGirl.create(:connection, :user => creator2, :music_session => later_session)

      user = FactoryGirl.create(:user)
      FactoryGirl.create(:friendship, :user => creator1, :friend => user)
      FactoryGirl.create(:friendship, :user => user, :friend => creator1)
      FactoryGirl.create(:connection, :user => creator1, :music_session => earlier_session)
      FactoryGirl.create(:connection, :user => creator2, :music_session => earlier_session)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 2
      music_sessions.first.id.should == earlier_session.id
    end

    it "doesn't list a session if musician_access is set to false" do
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false)
      user = FactoryGirl.create(:user)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 0
    end

    it "does list a session if musician_access is set to false but user was invited" do
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :musician_access => false)
      user = FactoryGirl.create(:user)
      FactoryGirl.create(:connection, :user => creator, :music_session => session)
      FactoryGirl.create(:friendship, :user => creator, :friend => user)
      FactoryGirl.create(:friendship, :user => user, :friend => creator)
      FactoryGirl.create(:invitation, :sender => creator, :receiver => user, :music_session => session.music_session)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 1
    end

    it "lists a session if the genre matches" do
      creator = FactoryGirl.create(:user)
      genre = FactoryGirl.create(:genre)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre)
      FactoryGirl.create(:connection, :user => creator, :music_session => session)
      user = FactoryGirl.create(:user)

      music_sessions = ActiveMusicSession.index(user, genres: [genre.id])
      music_sessions.length.should == 1
    end

    it "does not list a session if the genre fails to match" do
      creator = FactoryGirl.create(:user)
      genre1 = FactoryGirl.create(:genre)
      genre2 = FactoryGirl.create(:genre)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :genre => genre1)
      user = FactoryGirl.create(:user)

      music_sessions = ActiveMusicSession.index(user, genres: [genre2.id])
      music_sessions.length.should == 0
    end

    it "does not list a session if friends_only is set and no friends are in it" do
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
      user = FactoryGirl.create(:user)

      music_sessions = ActiveMusicSession.index(user, friends_only: true)
      music_sessions.length.should == 0
    end

    it "lists a session properly if a friend is in it" do
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
      user = FactoryGirl.create(:user)
      FactoryGirl.create(:friendship, :user => creator, :friend => user)
      FactoryGirl.create(:friendship, :user => user, :friend => creator)
      FactoryGirl.create(:connection, :user => creator, :music_session => session)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 1
      music_sessions = ActiveMusicSession.index(user, friends_only: true)
      music_sessions.length.should == 1
      music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
      music_sessions.length.should == 0
      music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true)
      music_sessions.length.should == 1
    end

    it "does not list a session if it has no participants" do
      # it's a design goal that there should be no sessions with 0 connections;
      # however, this bug continually crops up so the .index method will protect against this common bug

      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
      session.connections.delete_all # should leave a bogus, 0 participant session around

      music_sessions = ActiveMusicSession.index(creator)
      music_sessions.length.should == 0

    end

    it "does not list a session if my_bands_only is set and it's not my band" do
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session")
      user = FactoryGirl.create(:user)

      music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
      music_sessions.length.should == 0
    end

    it "lists a session properly if it's my band's session" do
      band = FactoryGirl.create(:band)
      creator = FactoryGirl.create(:user)
      session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Session", :band => band)
      FactoryGirl.create(:connection, :user => creator, :music_session => session)
      user = FactoryGirl.create(:user)
      FactoryGirl.create(:band_musician, :band => band, :user => creator)
      FactoryGirl.create(:band_musician, :band => band, :user => user)

      music_sessions = ActiveMusicSession.index(user)
      music_sessions.length.should == 1
      music_sessions = ActiveMusicSession.index(user, friends_only: true)
      music_sessions.length.should == 0
      music_sessions = ActiveMusicSession.index(user, friends_only: false, my_bands_only: true)
      music_sessions.length.should == 1
      music_sessions = ActiveMusicSession.index(user, friends_only: true, my_bands_only: true)
      music_sessions.length.should == 1
    end

    describe "index(as_musician: false)" do
      let(:fan_access) { true }
      let(:creator) { FactoryGirl.create(:user) }
      let(:session) { FactoryGirl.create(:active_music_session, creator: creator, fan_access: fan_access) }
      let(:connection) { FactoryGirl.create(:connection, user: creator, :music_session => session) }

      let(:user) { FactoryGirl.create(:user) }

      describe "no mount" do

        before(:each) do
          session.mount.should be_nil
        end

        it "no session listed if mount is nil" do
          connection.touch
          sessions = ActiveMusicSession.index(user, as_musician: false)
          sessions.length.should == 0
        end
      end

      describe "with mount" do
        let(:session_with_mount) { FactoryGirl.create(:active_music_session_with_mount) }
        let(:connection_with_mount) { FactoryGirl.create(:connection, user: creator, :music_session => session_with_mount) }


        before(:each) {
          session_with_mount.mount.should_not be_nil
        }

        it "no session listed if icecast_server config hasn't been updated" do
          connection_with_mount.touch
          sessions = ActiveMusicSession.index(user, as_musician: false)
          sessions.length.should == 0
        end

        it "session listed if icecast_server config has been updated" do
          connection_with_mount.touch
          session_with_mount.created_at = 2.minutes.ago
          session_with_mount.save!(:validate => false)
          session_with_mount.mount.server.config_updated_at = 1.minute.ago
          session_with_mount.mount.server.save!(:validate => false)
          sessions = ActiveMusicSession.index(user, as_musician: false)
          sessions.length.should == 1
        end
      end

    end
  end

  describe "nindex" do
    it "nindex orders two sessions by created_at starting with most recent" do
      creator = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)

      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
      c1 = FactoryGirl.create(:connection, user: creator, music_session: earlier_session, addr: 0x01020304, locidispid: 1)

      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      c2 = FactoryGirl.create(:connection, user: creator2, music_session: later_session, addr: 0x21020304, locidispid: 2)

      user = FactoryGirl.create(:user)
      c3 = FactoryGirl.create(:connection, user: user, locidispid: 3)

      Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil);
      Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil);

      # scores!

      #ActiveRecord::Base.logger = Logger.new(STDOUT)
      music_sessions = ActiveMusicSession.nindex(user, client_id: c3.client_id).take(100)
      #music_sessions = MusicSession.index(user).take(100)
      #ActiveRecord::Base.logger = nil

      music_sessions.length.should == 2
      music_sessions[0].id.should == later_session.id
      music_sessions[1].id.should == earlier_session.id
    end
  end


  def ams(user, params)
    ActiveRecord::Base.transaction do
      return ActiveMusicSession.ams_index(user, params)
    end
  end


  describe "public index", no_transaction: false do
    it "public_index" do

      creator = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)
      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      user = FactoryGirl.create(:user)
      earlier_session.music_session.musician_access = true
      earlier_session.music_session.save!


      music_sessions = ActiveMusicSession.public_index(creator, {}).take(100)
      music_sessions.should_not be_nil
      music_sessions.length.should == 2
    end
  end


  describe "friend_active_index", no_transaction: false do
    it "does not crash" do

      creator = FactoryGirl.create(:user)
      creator2 = FactoryGirl.create(:user)
      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      user = FactoryGirl.create(:user)
      earlier_session.music_session.musician_access = false
      earlier_session.music_session.save!

      Friendship.save_using_models(creator, creator2)

      music_sessions = ActiveMusicSession.friend_active_index(creator, {}).take(100)
      music_sessions.should_not be_nil
      music_sessions.length.should == 2
    end

    describe "parameters" do
      let(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) }
      let(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr: 4) }
      let(:creator_2) { FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 10) }
      let(:creator_conn_2) { FactoryGirl.create(:connection, user: creator_2, ip_address: '4.4.4.4', locidispid: 1, addr: 1) }
      let(:creator_3) { FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 12) }
      let(:creator_conn_3) { FactoryGirl.create(:connection, user: creator_3, ip_address: '5.5.5.5', locidispid: 2, addr: 2) }
      let(:searcher_1) { FactoryGirl.create(:user, last_jam_locidispid: 5, last_jam_audio_latency: 6) }
      let(:searcher_conn_1) { FactoryGirl.create(:connection, user: searcher_1, ip_address: '8.8.8.8', locidispid: 5, addr: 5) }
      let(:searcher_2) { FactoryGirl.create(:user, last_jam_locidispid: 3, last_jam_audio_latency: 14) }
      let(:searcher_conn_2) { FactoryGirl.create(:connection, user: searcher_2, ip_address: '9.9.9.9', locidispid: 3, addr: 3) }


      let!(:music_session_1) { FactoryGirl.create(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps") }
      let!(:music_session_2) { FactoryGirl.create(:active_music_session, :creator => creator_2, genre: Genre.find('ambient'), language: 'spa', description: "Play with us as we jam to beatles and bunnies") }

      let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] }

      it "as invited" do

        music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
        music_sessions.length.should == 0

        Friendship.save_using_models(searcher_1, creator_1)
        FactoryGirl.create(:invitation, music_session: music_session_1.music_session, sender: creator_1, receiver: searcher_1)

        music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
        music_sessions.length.should == 1
        music_sessions[0].should == music_session_1.music_session
      end

      it "as rsvp" do

        music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
        music_sessions.length.should == 0

        rsvp_slot = FactoryGirl.create(:rsvp_slot, music_session: music_session_1.music_session, instrument: Instrument.find('piano'))
        rsvp_request = FactoryGirl.create(:rsvp_request, user: searcher_1, chosen: true, music_session: music_session_1.music_session)
        rsvp_request_rsvp_slot = FactoryGirl.create(:rsvp_request_rsvp_slot, chosen: true, rsvp_request: rsvp_request, rsvp_slot: rsvp_slot)


        music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
        music_sessions.length.should == 1
        music_sessions[0].should == music_session_1.music_session
      end

      describe "as friends" do

        before(:each) {
          Friendship.save_using_models(searcher_1, creator_1)
          Friendship.save_using_models(searcher_1, creator_2)
        }

        it "offset/limit" do
          # put creators in the session
          creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10)
          creator_conn_1.errors.any?.should be_false
          creator_conn_2.join_the_session(music_session_2.music_session, true, tracks, creator_2, 10)
          creator_conn_2.errors.any?.should be_false

          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
          music_sessions.length.should == 2
          music_sessions[0].should == music_session_2.music_session

          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, offset: 0, limit: 1)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_2.music_session

          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, offset: 1, limit: 2)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_1.music_session
        end

        it "genre" do
          # verify we can get all 2 sessions
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
          music_sessions.length.should == 2

          # get only african
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, genre: 'african')
          music_sessions.length.should == 1
          music_sessions[0].genre.should == Genre.find('african')

          # get only ambient
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, genre: 'ambient')
          music_sessions.length.should == 1
          music_sessions[0].genre.should == Genre.find('ambient')
        end

        it "language" do
          # verify we can get all 2 sessions
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, {})
          music_sessions.length.should == 2

          # get only english
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, lang: 'eng')
          music_sessions.length.should == 1
          music_sessions[0].language.should == 'eng'

          # get only ambient
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, lang: 'spa')
          music_sessions.length.should == 1
          music_sessions[0].language.should == 'spa'

        end

        it "keyword" do
          pending "Test with ActiveMusicSession.public_index instead"
          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, keyword: 'Jump')
          music_sessions.length.should == 1

          music_sessions[0].should == music_session_1.music_session
          music_sessions = ams(searcher_1, keyword: 'Bunny')
          music_sessions.length.should == 2

          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, keyword: 'play')
          music_sessions.length.should == 1

          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, keyword: 'bun')
          music_sessions.length.should == 2


          music_sessions = ActiveMusicSession.friend_active_index(searcher_1, keyword: 'bunny play')
          music_sessions.length.should == 1
        end
      end
    end

  end

  describe "ams_index", no_transaction: true do
    it "does not crash" do

      creator = FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 5)
      creator2 = FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 10)

      earlier_session = FactoryGirl.create(:active_music_session, :creator => creator, :description => "Earlier Session")
      c1 = FactoryGirl.create(:connection, user: creator, music_session: earlier_session, locidispid: 1, last_jam_audio_latency: 5)

      later_session = FactoryGirl.create(:active_music_session, :creator => creator2, :description => "Later Session")
      c2 = FactoryGirl.create(:connection, user: creator2, music_session: later_session, locidispid: 2, last_jam_audio_latency: 10)

      user = FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 5)
      c3 = FactoryGirl.create(:connection, user: user, locidispid: 1, last_jam_audio_latency: 5)

      Score.createx(c1.locidispid, c1.client_id, c1.addr, c3.locidispid, c3.client_id, c3.addr, 20, nil, nil, {auserid: creator.id, buserid: user.id})
      Score.createx(c2.locidispid, c2.client_id, c2.addr, c3.locidispid, c3.client_id, c3.addr, 30, nil, nil, {auserid: creator2.id, buserid: user.id})

      # make a transaction

      ActiveRecord::Base.transaction do

        ActiveMusicSession.ams_init(user, client_id: c3.client_id)

        music_sessions = ActiveMusicSession.ams_query(user, client_id: c3.client_id).take(100)
        music_sessions.should_not be_nil
        music_sessions.length.should == 2
        music_sessions[0].tag.should_not be_nil
        music_sessions[0].latency.should_not be_nil
        music_sessions[1].tag.should_not be_nil
        music_sessions[1].latency.should_not be_nil

        users = ActiveMusicSession.ams_users.take(100)
        users.should_not be_nil
        users.length.should == 2

        if users[0].music_session_id == earlier_session.id
          users[0].id.should == creator.id
          users[0].full_score.should == 30 # (5 + 20 + 5)
          users[0].audio_latency = 5
          users[0].internet_score = 20
          users[1].music_session_id == later_session.id
          users[1].id.should == creator2.id
          users[1].full_score.should == 45 # (5 + 30 + 10)
          users[1].audio_latency.should == 10
          users[1].internet_score.should == 30
        else
          users[0].music_session_id.should == later_session.id
          users[0].id.should == creator2.id
          users[0].full_score.should == 45 # (5 + 30 + 10)
          users[0].audio_latency.should == 10
          users[0].internet_score.should == 30
          users[1].music_session_id == earlier_session.id
          users[1].id.should == creator.id
          users[1].full_score.should == 30 # (5 + 20 + 5)
          users[1].audio_latency.should == 5
          users[1].internet_score.should == 20
        end
      end
    end

    describe "parameters" do
      before {
        pending "Test instead ActiveMusicSession.public_index"
      }
      let(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) }
      let(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr: 4) }
      let(:creator_2) { FactoryGirl.create(:user, last_jam_locidispid: 1, last_jam_audio_latency: 10) }
      let(:creator_conn_2) { FactoryGirl.create(:connection, user: creator_2, ip_address: '4.4.4.4', locidispid: 1, addr: 1) }
      let(:creator_3) { FactoryGirl.create(:user, last_jam_locidispid: 2, last_jam_audio_latency: 12) }
      let(:creator_conn_3) { FactoryGirl.create(:connection, user: creator_3, ip_address: '5.5.5.5', locidispid: 2, addr: 2) }
      let(:searcher_1) { FactoryGirl.create(:user, last_jam_locidispid: 5, last_jam_audio_latency: 6) }
      let(:searcher_conn_1) { FactoryGirl.create(:connection, user: searcher_1, ip_address: '8.8.8.8', locidispid: 5, addr: 5) }
      let(:searcher_2) { FactoryGirl.create(:user, last_jam_locidispid: 3, last_jam_audio_latency: 14) }
      let(:searcher_conn_2) { FactoryGirl.create(:connection, user: searcher_2, ip_address: '9.9.9.9', locidispid: 3, addr: 3) }

      let!(:music_session_1) { FactoryGirl.create(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps") }
      let!(:music_session_2) { FactoryGirl.create(:active_music_session, :creator => creator_2, genre: Genre.find('ambient'), language: 'spa', description: "Play with us as we jam to beatles and bunnies") }

      let(:good_network_score) { 20 }
      let(:fair_network_score) { 30 }
      let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] }

      it "offset/limit" do
        # put creators in the session
        creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10)
        creator_conn_1.errors.any?.should be_false
        creator_conn_2.join_the_session(music_session_2.music_session, true, tracks, creator_2, 10)
        creator_conn_2.errors.any?.should be_false

        # set up some scores to control sorting
        Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_1.locidispid, creator_conn_1.client_id, creator_conn_1.addr, good_network_score, nil)
        Score.createx(searcher_conn_1.locidispid, searcher_conn_1.client_id, searcher_conn_1.addr, creator_conn_2.locidispid, creator_conn_2.client_id, creator_conn_2.addr, fair_network_score, nil)

        # verify we can get all 2 sessions
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id)
          music_sessions.length.should == 2
          music_sessions[0].should == music_session_1.music_session
        end

        # grab just the 1st
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, offset: 0, limit: 1)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_1.music_session
        end

        # then the second
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, offset: 1, limit: 2)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_2.music_session
        end
      end

      it "genre" do
        # verify we can get all 2 sessions
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id)
          music_sessions.length.should == 2
        end

        # get only african
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, genre: 'african')
          music_sessions.length.should == 1
          music_sessions[0].genre.should == Genre.find('african')
        end

        # get only ambient
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, genre: 'ambient')
          music_sessions.length.should == 1
          music_sessions[0].genre.should == Genre.find('ambient')
        end
      end

      it "language" do
        # verify we can get all 2 sessions
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id)
          music_sessions.length.should == 2
        end

        # get only english
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, lang: 'eng')
          music_sessions.length.should == 1
          music_sessions[0].language.should == 'eng'
        end

        # get only ambient
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, lang: 'spa')
          music_sessions.length.should == 1
          music_sessions[0].language.should == 'spa'
        end
      end

      it "keyword" do
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Jump')
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_1.music_session
        end

        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'Bunny')
          music_sessions.length.should == 2
        end

        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'play')
          music_sessions.length.should == 1
        end

        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'bun')
          music_sessions.length.should == 2
        end

        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, keyword: 'bunny play')
          music_sessions.length.should == 1
        end
      end

      it "date" do
        music_session_1.music_session.scheduled_start = 1.days.ago
        music_session_1.music_session.save!

        # if no day/timezone_offset specified, both should be returned
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id)
          music_sessions.length.should == 2
        end


        # find today's session
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, day: Date.today.to_s, timezone_offset: DateTime.now.offset.numerator)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_2.music_session
        end


        # find yesterday's session
        ActiveRecord::Base.transaction do
          music_sessions, user_search = ams(searcher_1, client_id: searcher_conn_1.client_id, day: (Date.today - 1).to_s, timezone_offset: DateTime.now.offset.numerator)
          music_sessions.length.should == 1
          music_sessions[0].should == music_session_1.music_session
        end
      end

      it "should allow a null locidispid to search" do
        searcher_conn_1.locidispid = nil
        searcher_conn_1.save!
        ActiveRecord::Base.transaction do
          music_sessions, user_scores = ams(searcher_1, client_id: searcher_conn_1.client_id)
          music_sessions.length.should == 2
        end

      end
    end

    # todo we need more tests:
    #
    # the easiest collection of tests, not involving filtering, just tagging and latency, still result in many cases
    # (given a creator, member, and observer):
    #
    # {not_rsvp, rsvp_not_chosen, rsvp_chosen} x
    # {not_invited, invited} x
    # {no_musicians, musicians_on_approval, musicians_freely_join} x
    # {creator_not_member, creator_is_member} x
    # {observer_not_member, observer_is_member} x
    # {observer_member_not_scored, observer_member_scored}
    #
    # eh, that's 144 cases all told, and that doesn't cover the cases with multiple members...
    #
    # member is the user in the session
    # creator is the user that created the session
    # observer is the user making the call to ams_index
    #
    # the first two categories (rsvp and invited) are about the observer.
    #
    # i see this being written like this:
    #
    # test_ams([:not_rsvp, :not_invited, :no_musicians, :creator_not_member, :observer_not_member, :observer_member_not_scored],
    #   member_latency, observer_member_score, observer_latency, expected_count, expected_tag, expected_latency)
    #
    # ... repeat as above with all the various combinations by choosing one from each category and appropriate other
    # values and then expected results ...
    #
    # expected_count is 0 for the above written case, and would be 1 in the cases where any of rsvp_chosen, invited,
    # musicians_on_approval, or musicians_freely_join are specified. test_ams would know which session and user should
    # appear in the results of ams_index and ams_users.
    #
    # there should be an additional active music session created and joined by a distinct user, other. it should never
    # appear in results.
  end


  it 'uninvited users cant join approval-required sessions without invitation' do
    user1 = FactoryGirl.create(:user) # in the jam session
    user2 = FactoryGirl.create(:user) # in the jam session

    music_session = FactoryGirl.create(:active_music_session, :creator => user1, :musician_access => true, :approval_required => true)

    connection1 = FactoryGirl.create(:connection, :user => user1, :music_session => music_session)
    expect { FactoryGirl.create(:connection, :user => user2, :music_session => music_session, :joining_session => true) }.to raise_error(ActiveRecord::RecordInvalid)

  end


  it "is_recording? returns false if not recording" do
    user1 = FactoryGirl.create(:user)
    music_session = FactoryGirl.build(:active_music_session, :creator => user1)
    music_session.is_recording?.should be_false
  end


  describe "open_jam_track" do
    before(:each) do
      @user1 = FactoryGirl.create(:user)
      @connection = FactoryGirl.create(:connection, :user => @user1)
      @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
      @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
      @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
      # @music_session.connections << @connection
      @music_session.save!
      @connection.join_the_session(@music_session, true, nil, @user1, 10)
      @jam_track = FactoryGirl.create(:jam_track)
      @jam_track_right = FactoryGirl.create(:jam_track_right, jam_track: @jam_track, user: @user1)
    end

    it "allow a jam track to be associated" do
      # simple success case; just open the jam track and observe the state of the session is correct
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.jam_track.should == @jam_track
      @music_session.jam_track_initiator.should == @user1
    end

    it "allow a jam track to be closed" do
      # simple success case; close an opened jam track and observe the state of the session is correct
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_false
      @music_session.close_jam_track
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.jam_track.should be_nil
      @music_session.jam_track_initiator.should be_nil
    end

    it "disallow a jam track to be opened when another is already opened" do
      pending "needs fixing"
      # if a jam track is open, don't allow another to be opened
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_false
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:jam_track] == [ValidationMessages::JAM_TRACK_ALREADY_OPEN]
    end

    it "disallow a jam track to be opened when recording is ongoing" do
      @recording = Recording.start(@music_session, @user1)
      @music_session.errors.any?.should be_false
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:jam_track] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS]
    end

    it "disallow a jam track to be opened when recording is playing back" do
      # create a recording, and open it for play back
      @recording = Recording.start(@music_session, @user1)
      @recording.errors.any?.should be_false
      @recording.stop
      @recording.reload
      @claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true)
      @claimed_recording.errors.any?.should be_false
      @music_session.claimed_recording_start(@user1, @claimed_recording)
      @music_session.errors.any?.should be_false

      # while it's open, try to open a jam track
      @music_session.open_jam_track(@user1, @jam_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:jam_track] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS]
    end

  end


  describe "recordings" do

    before(:each) do
      @user1 = FactoryGirl.create(:user)
      @connection = FactoryGirl.create(:connection, :user => @user1)
      @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
      @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
      @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
      # @music_session.connections << @connection
      @music_session.save!
      @connection.join_the_session(@music_session, true, nil, @user1, 10)
    end

    describe "not recording" do
      it "stop_recording should return nil if not recording" do
        @music_session.stop_recording.should be_nil
      end
    end

    describe "currently recording" do
      before(:each) do
        @recording = FactoryGirl.create(:recording, :music_session => @music_session, :owner => @user1)
      end

      it "is_recording? returns true if recording" do
        @music_session.is_recording?.should be_true
      end

      it "stop_recording should return recording object if recording" do
        @music_session.stop_recording.should == @recording
      end
    end

    describe "open a recording" do

      before(:each) do
        @recording = Recording.start(@music_session, @user1)
        @recording.errors.any?.should be_false
        @recording.stop
        @recording.reload
        @claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true)
        @claimed_recording.errors.any?.should be_false
      end

      it "allow a claimed recording to be associated" do
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_false
        @music_session.reload
        @music_session.claimed_recording.should == @claimed_recording
        @music_session.claimed_recording_initiator.should == @user1
      end

      it "allow a claimed recording to be removed" do
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_false
        @music_session.claimed_recording_stop
        @music_session.errors.any?.should be_false
        @music_session.reload
        @music_session.claimed_recording.should be_nil
        @music_session.claimed_recording_initiator.should be_nil
      end

      it "disallow a claimed recording to be started when already started by someone else" do
        @user2 = FactoryGirl.create(:user)
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_false
        @music_session.claimed_recording_start(@user2, @claimed_recording)
        @music_session.errors.any?.should be_true
        @music_session.errors[:claimed_recording] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS]
      end

      it "disallow a claimed recording to be started when already started by self" do
        @user2 = FactoryGirl.create(:user)
        @claimed_recording2 = @recording.claim(@user1, "name", "description", Genre.first, true)
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_false
        @music_session.claimed_recording_start(@user1, @claimed_recording2)
        @music_session.errors.any?.should be_true
      end

      it "disallow a claimed recording to be started when jam track is open" do
        # open the jam track
        @jam_track = FactoryGirl.create(:jam_track)
        @jam_track_right = FactoryGirl.create(:jam_track_right, jam_track: @jam_track, user: @user1)
        @music_session.open_jam_track(@user1, @jam_track)
        @music_session.errors.any?.should be_false

        # and try to open a recording for playback
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_true
        @music_session.errors[:claimed_recording] == [ValidationMessages::JAM_TRACK_ALREADY_OPEN]

      end

      it "disallow a claimed recording to be started when backing track is open" do
        # open the backing track
        @backing_track = "foo.mp3"
        @music_session.open_backing_track(@user1, @backing_track)
        @music_session.errors.any?.should be_false

        # and try to open a recording for playback
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_true
        @music_session.errors[:claimed_recording] == [ValidationMessages::BACKING_TRACK_ALREADY_OPEN]
      end

      it "disallow a claimed recording to be started when metronome is open" do
        # open the metronome
        @music_session.open_metronome(@user1)
        @music_session.errors.any?.should be_false

        # and try to open a recording for playback
        @music_session.claimed_recording_start(@user1, @claimed_recording)
        @music_session.errors.any?.should be_true
        @music_session.errors[:claimed_recording] == [ValidationMessages::METRONOME_ALREADY_OPEN]
      end
    end
  end

  describe "updates parent music_session" do
    it "updates needed fields" do
      music_session = FactoryGirl.create(:music_session, scheduled_start: nil)
      active_music_session = FactoryGirl.create(:active_music_session, music_session: music_session)
      music_session.reload
      active_music_session.reload
      music_session.scheduled_start.to_s.should == active_music_session.created_at.to_s
      music_session.active_music_session.should == active_music_session
    end

    it "ignore scheduled_start if already set" do

      yesterday = 1.days.ago
      music_session = FactoryGirl.create(:music_session, scheduled_start: yesterday)
      active_music_session = FactoryGirl.create(:active_music_session, music_session: music_session)
      music_session.reload
      music_session.scheduled_start.to_i.should == yesterday.utc.to_i
    end
  end

  describe "get_connection_ids" do
    before(:each) do
      @user1 = FactoryGirl.create(:user)
      @user2 = FactoryGirl.create(:user)
      @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
      @connection1 = FactoryGirl.create(:connection, :user => @user1, :music_session => @music_session, :as_musician => true)
      @connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session, :as_musician => false)

    end

    it "get all connections" do
      @music_session.get_connection_ids().should == [@connection1.client_id, @connection2.client_id]
    end

    it "exclude non-musicians" do
      @music_session.get_connection_ids(as_musician: true).should == [@connection1.client_id]
    end

    it "exclude musicians" do
      @music_session.get_connection_ids(as_musician: false).should == [@connection2.client_id]
    end

    it "exclude particular client" do
      @music_session.get_connection_ids(exclude_client_id: @connection1.client_id).should == [@connection2.client_id]
    end

    it "exclude particular client and exclude non-musicians" do
      @music_session.get_connection_ids(exclude_client_id: @connection2.client_id, as_musician: true).should == [@connection1.client_id]
    end
  end

  describe "join_the_session" do
    let(:creator_1) { FactoryGirl.create(:user, last_jam_locidispid: 4, last_jam_audio_latency: 8) }
    let(:creator_conn_1) { FactoryGirl.create(:connection, user: creator_1, ip_address: '4.4.4.4', locidispid: 4, addr: 4) }
    let!(:music_session_1) { FactoryGirl.create(:active_music_session, :creator => creator_1, genre: Genre.find('african'), language: 'eng', description: "Bunny Jumps") }
    let(:tracks) { [{'sound' => 'mono', 'client_track_id' => 'abc', 'instrument_id' => 'piano'}] }
    let(:videos) { [{'client_video_source_id' => 'abc'}] }

    it "joins the session with no video" do
      creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10)
      creator_conn_1.errors.any?.should be_false

      music_sessions = ActiveMusicSession.index(creator_1)
      music_sessions.should_not be_nil
      music_sessions.length.should == 1
      music_sessions[0].connections.should have(1).items
      music_sessions[0].connections.should have(1).items
      music_sessions[0].connections[0].tracks.should have(1).items
      music_sessions[0].connections[0].video_sources.should have(0).items
    end

    it "joins the session with video" do
      creator_conn_1.join_the_session(music_session_1.music_session, true, tracks, creator_1, 10, nil, nil, videos)
      creator_conn_1.errors.any?.should be_false
      music_sessions = ActiveMusicSession.index(creator_1)
      music_sessions.should_not be_nil
      music_sessions.length.should == 1
      creator_conn_1.video_sources.should have(1).items
      music_sessions[0].connections.should have(1).items
      music_sessions[0].connections[0].video_sources.should have(1).items
      music_sessions[0].connections[0].tracks.should have(1).items
    end
  end

  describe "open_backing_track" do
    before(:each) do
      @user1 = FactoryGirl.create(:user)
      @connection = FactoryGirl.create(:connection, :user => @user1)
      @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
      @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
      @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
      # @music_session.connections << @connection
      @music_session.save!
      @connection.join_the_session(@music_session, true, nil, @user1, 10)
      @backing_track = "foo/bar.mp3"
    end

    it "allow a backing track to be associated" do
      # simple success case; just open the backing track and observe the state of the session is correct
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.backing_track_path.should == @backing_track
      @music_session.backing_track_initiator.should == @user1
    end

    it "allow a backing track to be closed" do
      # simple success case; close an opened backing track and observe the state of the session is correct
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_false
      @music_session.close_backing_track
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.backing_track_path.should be_nil
      @music_session.backing_track_initiator.should be_nil
    end

    it "disallow a backing track to be opened when another is already opened" do
      # if a backing track is open, don't allow another to be opened
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_false
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:backing_track] == [ValidationMessages::BACKING_TRACK_ALREADY_OPEN]
    end

    it "disallow a backing track to be opened when recording is ongoing" do
      @recording = Recording.start(@music_session, @user1)
      @music_session.errors.any?.should be_false
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:backing_track] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS]
    end

    it "disallow a backing track to be opened when recording is playing back" do
      # create a recording, and open it for play back
      @recording = Recording.start(@music_session, @user1)
      @recording.errors.any?.should be_false
      @recording.stop
      @recording.reload
      @claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true)
      @claimed_recording.errors.any?.should be_false
      @music_session.claimed_recording_start(@user1, @claimed_recording)
      @music_session.errors.any?.should be_false

      # while it's open, try to open a jam track
      @music_session.open_backing_track(@user1, @backing_track)
      @music_session.errors.any?.should be_true
      @music_session.errors[:backing_track] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS]
    end

  end

  describe "play_time_remaining" do
    it "checks all" do
      user = FactoryGirl.create(:user)
      music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => false)

      user.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = SubscriptionDefinitions::JAM_PLATINUM_YEARLY
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = SubscriptionDefinitions::JAM_GOLD
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = SubscriptionDefinitions::JAM_GOLD_YEARLY
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = SubscriptionDefinitions::JAM_SILVER
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = SubscriptionDefinitions::JAM_SILVER_YEARLY
      music_session.play_time_remaining(user).should be_nil

      user.subscription_plan_code = nil
      music_session.play_time_remaining(user).should_not be_nil
    end
  end

  describe "open_metronome" do
    before(:each) do
      @user1 = FactoryGirl.create(:user)
      @connection = FactoryGirl.create(:connection, :user => @user1)
      @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
      @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
      @music_session = FactoryGirl.create(:active_music_session, :creator => @user1, :musician_access => true)
      # @music_session.connections << @connection
      @music_session.save!
      @connection.join_the_session(@music_session, true, nil, @user1, 10)
    end

    it "allow a metronome to be activated" do
      # simple success case; just open the metronome and observe the state of the session is correct
      @music_session.open_metronome(@user1)
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.metronome_active.should == true
      @music_session.metronome_initiator.should == @user1
    end

    it "allow a metronome to be closed" do
      # simple success case; close an opened metronome and observe the state of the session is correct
      @music_session.open_metronome(@user1)
      @music_session.errors.any?.should be_false
      @music_session.close_metronome
      @music_session.errors.any?.should be_false
      @music_session.reload
      @music_session.metronome_active.should be_false
      @music_session.metronome_initiator.should be_nil
    end

    it "disallow a metronome to be opened when recording is ongoing" do
      @recording = Recording.start(@music_session, @user1)
      @music_session.errors.any?.should be_false
      @music_session.open_metronome(@user1)
      @music_session.errors.any?.should be_true
      @music_session.errors[:metronome] == [ValidationMessages::RECORDING_ALREADY_IN_PROGRESS]
    end

    it "disallow a metronome to be opened when recording is playing back" do
      # create a recording, and open it for play back
      @recording = Recording.start(@music_session, @user1)
      @recording.errors.any?.should be_false
      @recording.stop
      @recording.reload
      @claimed_recording = @recording.claim(@user1, "name", "description", Genre.first, true)
      @claimed_recording.errors.any?.should be_false
      @music_session.claimed_recording_start(@user1, @claimed_recording)
      @music_session.errors.any?.should be_false

      # while it's open, try to open a jam track
      @music_session.open_metronome(@user1)
      @music_session.errors.any?.should be_true
      @music_session.errors[:metronome] == [ValidationMessages::CLAIMED_RECORDING_ALREADY_IN_PROGRESS]
    end

  end

  describe "stats" do
    it "empty" do
      ActiveMusicSession.stats['count'].should eq(0)
    end


    it "one" do
      FactoryGirl.create(:active_music_session)
      ActiveMusicSession.stats.should eq('count' => 1,
                                         'jam_track_count' => 0,
                                         'backing_track_count' => 0,
                                         'metronome_count' => 0,
                                         'recording_count' => 0)
    end

    it "two" do
      ams1 = FactoryGirl.create(:active_music_session, jam_track_initiator_id: '1')
      ams2 = FactoryGirl.create(:active_music_session, jam_track_initiator_id: '2')
      user1 = FactoryGirl.create(:user)
      user2 = FactoryGirl.create(:user)
      ActiveMusicSession.stats.should eq('count' => 2,
                                         'jam_track_count' => 2,
                                         'backing_track_count' => 0,
                                         'metronome_count' => 0,
                                         'recording_count' => 0)

      ams1.backing_track_initiator = user1
      ams2.backing_track_initiator = user2
      ams1.save!
      ams2.save!

      ActiveMusicSession.stats.should eq('count' => 2,
                                         'jam_track_count' => 2,
                                         'backing_track_count' => 2,
                                         'metronome_count' => 0,
                                         'recording_count' => 0)

      ams1.metronome_initiator = user1
      ams2.metronome_initiator = user2
      ams1.save!
      ams2.save!

      ActiveMusicSession.stats.should eq('count' => 2,
                                         'jam_track_count' => 2,
                                         'backing_track_count' => 2,
                                         'metronome_count' => 2,
                                         'recording_count' => 0)

      ams1.claimed_recording_initiator = user1
      ams2.claimed_recording_initiator = user2
      ams1.save!
      ams2.save!

      ActiveMusicSession.stats.should eq('count' => 2,
                                         'jam_track_count' => 2,
                                         'backing_track_count' => 2,
                                         'metronome_count' => 2,
                                         'recording_count' => 2)

    end


  end

end

