require 'spec_helper'

describe MusicSessionUserHistory do

  let(:some_user) { FactoryGirl.create(:user) }
  let(:some_other_user) { FactoryGirl.create(:user) }
  let(:music_session) { FactoryGirl.create(:active_music_session_no_user_history) }
  let(:user_history1) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator) }
  let(:user_history2) { FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user) }


  after {
    Timecop.return
  }
  describe "create" do
    pending
    it {user_history1.music_session_id.should == music_session.id }
    it {user_history1.created_at.should_not be_nil }
    it {user_history1.session_removed_at.should be_nil }
  end

  describe "rating" do

    def stub_app_config
      #stubbing APP_CONFIG 
      app_config = Class.new{
        def rating_dialog_min_time
          60
        end

        def rating_dialog_min_num
          1
        end
      }
      stub_const("APP_CONFIG", app_config.new)
    end
   
    it "success" do
      user_history1.update_attribute(:rating, 1)
      expect( user_history1.errors.any? ).to eq(false)
    end

    it "out of range"  do
      user_history1.rating = 2
      user_history1.save
      expect( user_history1.errors.any? ).to eq(true)
    end

    it 'should rate success' do
      stub_app_config
      users = [user_history1, user_history2]
      Timecop.travel(Time.now + (APP_CONFIG.rating_dialog_min_time * 1.5).seconds)
      expect( user_history1.should_rate_session? ).to eq(true)
    end

    it 'should rate fails' do
      stub_app_config
      users = [user_history1]
      expect( user_history1.should_rate_session? ).to eq(false)
      users = [user_history1, user_history2]
      expect( user_history2.should_rate_session? ).to eq(false)
    end

  end

  describe "end_history" do
    pending
    it "histories created at the same time" do
      user_history1.reload
      user_history2.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 2
    end

    it "when history1 only" do
      user_history1.save.should be_true
      user_history1.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 1
    end

    it "history2 ends before history1 starts" do
      user_history2.created_at = user_history1.created_at - 2
      user_history2.session_removed_at = user_history1.created_at - 1
      user_history2.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 1
    end

    it "history2 starts after history1 starts" do
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 2
      user_history2.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 1
    end

    it "history2 begin before history1 starts and terminates before history1 end" do
      user_history1.session_removed_at = user_history1.created_at + 3
      user_history2.created_at = user_history1.created_at - 1
      user_history2.session_removed_at = user_history1.created_at + 2

      #user_history1.save.should be_true
      user_history2.save.should be_true

      expect(user_history1.session_removed_at).to be > user_history1.created_at
      expect(user_history2.session_removed_at).to be > user_history2.created_at

      user_history1.reload
      user_history2.reload
      user_history1.end_history
      
      user_history1.max_concurrent_connections.should == 2
    end

    it "history2 begin after history1 starts and terminates after history1 end" do
      user_history1.session_removed_at = user_history1.created_at + 3
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 4

      user_history1.save.should be_true
      user_history2.save.should be_true
      
      user_history1.reload
      user_history2.reload

      user_history1.end_history
      
      user_history1.max_concurrent_connections.should == 2
    end


    it "history2 is within bounds of history1 " do 
      user_history1.session_removed_at = user_history1.created_at + 3
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 2
      user_history1.save.should be_true
      user_history2.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 2
    end

    it "two histories with same user within bounds of history1" do
      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user)

      # if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
      user_history1.session_removed_at = user_history1.created_at + 5
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 2
      user_history3.created_at = user_history1.created_at + 3
      user_history3.session_removed_at = user_history1.created_at + 4
      user_history1.save.should be_true
      user_history2.save.should be_true
      user_history3.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history3.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 2
    end

    it "two histories with different user within bounds of history1" do
      third_user = FactoryGirl.create(:user);

      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => third_user)

      # if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
      user_history1.session_removed_at = user_history1.created_at + 5
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 2
      user_history3.created_at = user_history1.created_at + 3
      user_history3.session_removed_at = user_history1.created_at + 4
      user_history1.save.should be_true
      user_history2.save.should be_true
      user_history3.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history3.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 2
    end

    it "two overlapping histories with different user within bounds of history1" do
      third_user = FactoryGirl.create(:user);

      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => third_user)

      # if user2 comes and goes 2 times while user one is there, it shouldn't be a false 3
      user_history1.session_removed_at = user_history1.created_at + 5
      user_history2.created_at = user_history1.created_at + 1
      user_history2.session_removed_at = user_history1.created_at + 3
      user_history3.created_at = user_history1.created_at + 2
      user_history3.session_removed_at = user_history1.created_at + 4
      user_history1.save.should be_true
      user_history2.save.should be_true
      user_history3.save.should be_true
      user_history1.reload
      user_history2.reload
      user_history3.reload
      user_history1.end_history
      user_history1.max_concurrent_connections.should == 3
    end
  end

  describe "duration_minutes" do
    it "returns zero when history2 ends before history1 starts" do
      user_history1.session_removed_at = user_history1.created_at + 5
      user_history2.created_at = user_history1.created_at - 2
      user_history2.session_removed_at = user_history1.created_at - 1
      
      user_history2.save.should be_true

      user_history2.reload
      user_history1.end_history
      
      expect(user_history1.duration_minutes).to eq 0
    end

    it "returns zero when history2 starts after history1 ends" do
      
      user_history1.session_removed_at = user_history1.created_at + 5
      user_history2.created_at = user_history1.session_removed_at + 1
      user_history2.session_removed_at = user_history1.session_removed_at + 2

      user_history2.save.should be_true

      user_history2.reload
      user_history1.end_history
      
      #user_history1.max_concurrent_connections.should == 1

      expect(user_history1.duration_minutes).to eq 0
    end


    it "returns overlapped time when history2 is within bounds of history1" do
      #pending
      user_history1.session_removed_at = user_history1.created_at + 3*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = user_history1.created_at + 3*60
      
      user_history1.save.should be_true
      user_history2.save.should be_true
      
      user_history1.reload
      user_history2.reload
      user_history1.end_history
      #user_history1.max_concurrent_connections.should == 2
      expect(user_history1.duration_minutes).to eq 2
    end

    it "returns overlapped time when history2 is within bounds of history1 -- idempotent" do
      #pending
      user_history1.session_removed_at = user_history1.created_at + 3*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = user_history1.created_at + 3*60

      user_history1.save.should be_true
      user_history2.save.should be_true

      user_history1.reload
      user_history2.reload
      user_history1.end_history
      expect(user_history1.duration_minutes).to eq 2
      music_session.creator.reload
      expect(music_session.creator.used_month_play_time).to eq (2 * 60)

      # call it a second tiem
      user_history1.end_history
      expect(user_history1.duration_minutes).to eq 2
      music_session.creator.reload
      expect(music_session.creator.used_month_play_time).to eq (2 * 60)
    end

    it "returns overlapped time when history2 begings before history1 start and terminates before history1 end" do
      user_history1.session_removed_at = user_history1.created_at + 3*60
      user_history2.created_at = user_history1.created_at - 1*60
      user_history2.session_removed_at = user_history1.created_at + 2*60
      
      expect(user_history1.save).to eq true
      expect(user_history2.save).to eq true

      user_history1.reload
      user_history2.reload
      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 2
    end


    it "returns overlapped time when history2 begings after history1 start and terminates after history1 end" do
      user_history1.session_removed_at = user_history1.created_at + 3*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = user_history1.created_at + 4*60

      expect(user_history1.save).to eq true
      expect(user_history2.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 2
    end

    it "same user in same session does not rack up time" do

      same_user_history = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator)

      user_history1.session_removed_at = user_history1.created_at + 3*60
      same_user_history.created_at = user_history1.created_at + 1*60
      same_user_history.session_removed_at = user_history1.created_at + 4*60

      expect(user_history1.save).to eq true
      expect(same_user_history.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 0
    end

    it "3rd user has no bearing on accumulated time if same overlapping as 2nd user" do
      user_history1.session_removed_at = user_history1.created_at + 3*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = user_history1.created_at + 4*60
      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_other_user)
      user_history3.created_at = user_history1.created_at + 1*60
      user_history3.session_removed_at = user_history1.created_at + 4*60

      expect(user_history1.save).to eq true
      expect(user_history2.save).to eq true
      expect(user_history3.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 2
    end

    it "3rd user has some bearing on accumulated time if different overlapping as 2nd user" do
      user_history1.session_removed_at = user_history1.created_at + 7*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = user_history1.created_at + 3*60
      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_other_user)
      user_history3.created_at = user_history1.created_at + 2*60
      user_history3.session_removed_at = user_history1.created_at + 4*60

      expect(user_history1.save).to eq true
      expect(user_history2.save).to eq true
      expect(user_history3.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 3
    end

    it "two users where 1st guy leaves last, and no save of that record" do
      user_history1.session_removed_at = user_history1.created_at + 7*60
      user_history2.created_at = user_history1.created_at - 1*60
      user_history2.session_removed_at = user_history1.created_at + 3*60

      expect(user_history2.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 3
    end

    it "two users where users all leaves, but then come back to same session 2x" do
      user_history1.session_removed_at = user_history1.created_at + 7*60
      user_history2.created_at = user_history1.created_at - 1*60
      user_history2.session_removed_at = user_history1.created_at + 3*60

      expect(user_history2.save).to eq true

      user_history1.end_history

      # validate duration minutes works
      expect(user_history1.duration_minutes).to eq 3
      expect(music_session.creator.used_month_play_time).to be_nil
      music_session.creator.reload
      # and validate that the users rolling monthly play time is tracked correctly
      expect(music_session.creator.used_month_play_time).to eq 3 * 60 # this field tracks per second
      expect(music_session.creator.used_current_month).to eq (User.current_month)


      # COME BACK INTO SAME SESSION LATER

      user_history1_returns = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator)
      user_history2_returns = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user)

      user_history1_returns.created_at = user_history1.created_at + 8*60
      user_history1_returns.session_removed_at = user_history1.created_at + 16*60
      user_history2_returns.created_at = user_history1.created_at + 7*60
      user_history2_returns.session_removed_at = user_history1.created_at + 12*60

      expect(user_history1_returns.save).to eq true
      expect(user_history2_returns.save).to eq true

      user_history1_returns.end_history

      expect(user_history1_returns.duration_minutes).to eq 4
      expect(music_session.creator.used_month_play_time).to eq 3 * 60
      music_session.creator.reload
      # validate that the users rolling monthly play time is still tracked correctly
      expect(music_session.creator.used_month_play_time).to eq (3 + 4) * 60 # 3 minutes  + 4 minutes should be 7


      # AND COME BACK ONCE MORE
      user_history1_returns2 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => music_session.creator)
      user_history2_returns2 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_user)

      user_history1_returns2.created_at = user_history1.created_at + 20*60
      user_history1_returns2.session_removed_at = user_history1.created_at + 25*60
      user_history2_returns2.created_at = user_history1.created_at + 21*60
      user_history2_returns2.session_removed_at = user_history1.created_at + 22*60

      expect(user_history1_returns2.save).to eq true
      expect(user_history2_returns2.save).to eq true

      user_history1_returns2.end_history

      expect(user_history1_returns2.duration_minutes).to eq 1
      expect(music_session.creator.used_month_play_time).to eq (3 + 4) * 60
      music_session.creator.reload
      # validate that the users rolling monthly play time is still tracked correctly
      expect(music_session.creator.used_month_play_time).to eq (3 + 4 + 1) * 60
    end

    it "a null session_removed of other substituted with the msuh's session_removed" do
      user_history1.session_removed_at = user_history1.created_at + 7*60
      user_history2.created_at = user_history1.created_at + 1*60
      user_history2.session_removed_at = nil
      user_history3 = FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => some_other_user)
      user_history3.created_at = user_history1.created_at + 2*60
      user_history3.session_removed_at = nil

      expect(user_history1.save).to eq true
      expect(user_history2.save).to eq true
      expect(user_history3.save).to eq true

      user_history1.end_history

      expect(user_history1.duration_minutes).to eq 6
    end

  end
end


