require 'spec_helper'

describe Recording do

  include UsesTempFiles


  let(:s3_manager) { S3Manager.new(app_config.aws_bucket, app_config.aws_access_key_id, app_config.aws_secret_access_key) }

  before do
    @user = FactoryGirl.create(:user)
    @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
    @music_session = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
    @connection = FactoryGirl.create(:connection, :user => @user, :music_session => @music_session)
    @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
  end

  describe "create_immediately" do
    it "success with no video" do
      recording = Recording.create_immediately(@user, {name: 'My recording', description: nil, genre: Genre.first, record_video: false, is_public: true, upload_to_youtube: false})
      puts "recording errros #{recording.errors.inspect}"
      recording.errors.any?.should be_false
      recording.reload
      recording.claimed_recordings.count.should eql 1
      claim = recording.claimed_recordings.first
      claim.name.should eql 'My recording'
      claim.description.should be_nil
      claim.discarded.should be_false
      claim.user.should eql @user
      recording.owner.should eql @user
    end
  end
  describe "popular_recordings" do
    it "empty" do
      Recording.popular_recordings.length.should eq(0)
    end

    it "one public recording" do
      claim = FactoryGirl.create(:claimed_recording)

      claim.recording.is_done = true
      claim.recording.save!
      recordings = Recording.popular_recordings
      recordings.length.should eq(1)
      recordings[0].id.should eq(claim.recording.id)
    end

    it "one private recording" do
      claim = FactoryGirl.create(:claimed_recording, is_public: true)

      recordings = Recording.popular_recordings
      recordings.length.should eq(0)
    end
  end

  describe "cleanup_excessive_storage" do

    sample_audio='sample.file'
    in_directory_with_file(sample_audio)

    let(:user2) { FactoryGirl.create(:user) }
    let(:quick_mix) { FactoryGirl.create(:quick_mix) }
    let(:quick_mix2) {
      recording.recorded_tracks << FactoryGirl.create(:recorded_track, recording: recording, user: user2)
      recording.claimed_recordings << FactoryGirl.create(:claimed_recording, user: user2, recording: recording)
      recording.save!
      FactoryGirl.create(:quick_mix, autowire: false, recording: recording, user: user2) }
    let(:recording) { quick_mix.recording }

    before(:each) do
      content_for_file("ogg goodness")
    end

    it "cleans up nothing without failing" do
      QuickMix.cleanup_excessive_storage
    end

    it "leaves untouched no completed mixes" do


      recording.has_final_mix.should be_false
      recording.has_stream_mix.should be_false
      quick_mix.cleaned.should be_false

      QuickMix.cleanup_excessive_storage
      recording.reload
      quick_mix.reload

      recording.has_final_mix.should be_false
      recording.has_stream_mix.should be_false
      quick_mix.cleaned.should be_false

    end

    it "leaves untouched a completed quick mix if it's the only one and old enough" do
      s3_manager.upload(quick_mix.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix.filename('mp3'), sample_audio)
      quick_mix.completed = true
      quick_mix[:ogg_url] = quick_mix.filename('ogg')
      quick_mix[:mp3_url] = quick_mix.filename('mp3')
      quick_mix.completed_at = 10.days.ago
      quick_mix.save!
      recording.has_stream_mix = true
      recording.first_quick_mix_id = quick_mix.id
      recording.save!
      quick_mix.recording_id.should == recording.id

      QuickMix.cleanup_excessive_storage
      recording.reload
      quick_mix.reload

      recording.has_final_mix.should be_false
      recording.has_stream_mix.should be_true
      quick_mix.cleaned.should be_false
      quick_mix[:ogg_url].should_not be_nil
      quick_mix[:mp3_url].should_not be_nil
    end

    it "cleans up completed quick mix if their is a final mix" do
      s3_manager.upload(quick_mix.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix.filename('mp3'), sample_audio)
      quick_mix.completed = true
      quick_mix[:ogg_url] = quick_mix.filename('ogg')
      quick_mix[:mp3_url] = quick_mix.filename('mp3')
      quick_mix.completed_at = 10.days.ago
      quick_mix.save!
      recording.has_final_mix = true
      recording.has_stream_mix = true
      recording.first_quick_mix_id = quick_mix.id
      recording.save!
      quick_mix.recording_id.should == recording.id

      QuickMix.cleanup_excessive_storage
      recording.reload
      quick_mix.reload

      recording.has_final_mix.should be_true
      recording.has_stream_mix.should be_false
      recording.first_quick_mix_id.should be_nil
      quick_mix.cleaned.should be_true
      quick_mix[:ogg_url].should_not be_nil
      quick_mix[:mp3_url].should_not be_nil
      s3_manager.exists?(quick_mix.filename('ogg')).should be_false
      s3_manager.exists?(quick_mix.filename('mp3')).should be_false

    end

    it "cleans up one of two quick mixes" do
      # quick_mix2 should get cleaned up, but quick_mix1 should be left alone because we need at least one if has_final_mix = false
      quick_mix2.touch
      s3_manager.upload(quick_mix.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix.filename('mp3'), sample_audio)
      s3_manager.upload(quick_mix2.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix2.filename('mp3'), sample_audio)
      quick_mix.completed = true
      quick_mix[:ogg_url] = quick_mix.filename('ogg')
      quick_mix[:mp3_url] = quick_mix.filename('mp3')
      quick_mix.completed_at = 10.days.ago
      quick_mix.save!
      quick_mix2.completed = true
      quick_mix2[:ogg_url] = quick_mix.filename('ogg')
      quick_mix2[:mp3_url] = quick_mix.filename('mp3')
      quick_mix2.completed_at = 10.days.ago
      quick_mix2.save!
      recording.has_stream_mix = true
      recording.first_quick_mix_id = quick_mix.id
      recording.save!
      quick_mix.recording_id.should == recording.id

      QuickMix.cleanup_excessive_storage
      recording.reload
      quick_mix.reload
      quick_mix2.reload

      recording.has_final_mix.should be_false
      recording.has_stream_mix.should be_true
      recording.first_quick_mix_id.should_not be_nil
      quick_mix.cleaned.should be_false
      quick_mix[:ogg_url].should_not be_nil
      quick_mix[:mp3_url].should_not be_nil
      s3_manager.exists?(quick_mix.filename('ogg')).should be_true
      s3_manager.exists?(quick_mix.filename('mp3')).should be_true
      quick_mix2.cleaned.should be_true
      quick_mix2[:ogg_url].should_not be_nil
      quick_mix2[:mp3_url].should_not be_nil
      s3_manager.exists?(quick_mix2.filename('ogg')).should be_false
      s3_manager.exists?(quick_mix2.filename('mp3')).should be_false

    end

    it "cleans up all quick mixes if there is a final mix" do
      # quick_mix2 should get cleaned up, but quick_mix1 should be left alone because we need at least one if has_final_mix = false
      quick_mix2.touch
      s3_manager.upload(quick_mix.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix.filename('mp3'), sample_audio)
      s3_manager.upload(quick_mix2.filename('ogg'), sample_audio)
      s3_manager.upload(quick_mix2.filename('mp3'), sample_audio)
      quick_mix.completed = true
      quick_mix[:ogg_url] = quick_mix.filename('ogg')
      quick_mix[:mp3_url] = quick_mix.filename('mp3')
      quick_mix.completed_at = 10.days.ago
      quick_mix.save!
      quick_mix2.completed = true
      quick_mix2[:ogg_url] = quick_mix.filename('ogg')
      quick_mix2[:mp3_url] = quick_mix.filename('mp3')
      quick_mix2.completed_at = 10.days.ago
      quick_mix2.save!
      recording.has_final_mix = true
      recording.has_stream_mix = true
      recording.first_quick_mix_id = quick_mix.id
      recording.save!
      quick_mix.recording_id.should == recording.id

      QuickMix.cleanup_excessive_storage
      recording.reload
      quick_mix.reload
      quick_mix2.reload

      recording.has_final_mix.should be_true
      recording.has_stream_mix.should be_false
      recording.first_quick_mix_id.should be_nil
      quick_mix.cleaned.should be_true
      quick_mix[:ogg_url].should_not be_nil
      quick_mix[:mp3_url].should_not be_nil
      s3_manager.exists?(quick_mix.filename('ogg')).should be_false
      s3_manager.exists?(quick_mix.filename('mp3')).should be_false
      quick_mix2.cleaned.should be_true
      quick_mix2[:ogg_url].should_not be_nil
      quick_mix2[:mp3_url].should_not be_nil
      s3_manager.exists?(quick_mix2.filename('ogg')).should be_false
      s3_manager.exists?(quick_mix2.filename('mp3')).should be_false

    end
  end

  it "should allow finding of recorded tracks" do
    user2 = FactoryGirl.create(:user)
    connection2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session)
    track2 = FactoryGirl.create(:track, :connection => connection2, :instrument => @instrument)

    @recording = Recording.start(@music_session, @user)
    user1_recorded_tracks = @recording.recorded_tracks_for_user(@user)
    user1_recorded_tracks[0].should == @user.recorded_tracks[0]
    user1_recorded_tracks.length.should == 1
    user2_recorded_tracks = @recording.recorded_tracks_for_user(user2)
    user2_recorded_tracks.length.should == 1
    user2_recorded_tracks[0].should == user2.recorded_tracks[0]

    user1_recorded_tracks[0].discard = true
    user1_recorded_tracks[0].save!
  end

  it "should allow finding of backing tracks" do
    user2 = FactoryGirl.create(:user)
    connection2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session)
    track2 = FactoryGirl.create(:track, :connection => connection2, :instrument => @instrument)
    backing_track = FactoryGirl.create(:backing_track, :connection => connection2)


    @recording = Recording.start(@music_session, @user)
    @recording.recorded_backing_tracks_for_user(@user).length.should eq(0)
    user2_recorded_tracks = @recording.recorded_backing_tracks_for_user(user2)
    user2_recorded_tracks.length.should == 1
    user2_recorded_tracks[0].should == user2.recorded_backing_tracks[0]
  end

  it "should set up the recording properly when recording is started with 1 user in the session" do
    @music_session.is_recording?.should be_false
    @recording = Recording.start(@music_session, @user)
    @music_session.reload
    @music_session.recordings[0].should == @recording
    @recording.owner_id.should == @user.id

    @recorded_tracks = RecordedTrack.where(:recording_id => @recording.id)
    @recorded_tracks.length.should == 1
    @recorded_tracks.first.instrument_id == @track.instrument_id
    @recorded_tracks.first.user_id == @track.connection.user_id
  end

  it "should not start a recording if the session is already being recorded" do
    Recording.start(@music_session, @user).errors.any?.should be_false
    recording = Recording.start(@music_session, @user)

    recording.valid?.should_not be_true
    recording.errors[:music_session].should_not be_nil
  end

  it "should return the state to normal properly when you stop a recording" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @music_session.reload
    @music_session.is_recording?.should be_false
  end


  it "should error when you stop a recording twice" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.errors.any?.should be_false
    @recording.stop
    @recording.errors.any?.should be_true
  end

  it "should be able to start, stop then start a recording again for the same music session" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.keep(@user)
    @recording2 = Recording.start(@music_session, @user)
    @music_session.recordings.exists?(@recording2.id).should be_true
  end

  it "should NOT attach the recording to all users in a the music session when recording started" do
    @user2 = FactoryGirl.create(:user)
    @connection2 = FactoryGirl.create(:connection, :user => @user2)
    @instrument2 = FactoryGirl.create(:instrument, :description => 'a great instrument')
    @track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument2)

    # @music_session.connections << @connection2
    @connection2.join_the_session(@music_session, true, nil, @user2, 10)

    @recording = Recording.start(@music_session, @user)
    @user.recordings.length.should == 0
    #@user.recordings.first.should == @recording

    @user2.recordings.length.should == 0
    #@user2.recordings.first.should == @recording
  end

  it "should report correctly whether its tracks have been uploaded" do
    @recording = Recording.start(@music_session, @user)
    @recording.uploaded?.should == false
    @recording.stop
    @recording.reload
    @recording.uploaded?.should == false
    @recording.recorded_tracks.first.fully_uploaded = true
    @recording.uploaded?.should == true
  end

  it "should destroy a recording and all its recorded tracks properly" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @recorded_track = @recording.recorded_tracks.first
    @recording.destroy
    expect { Recording.find(@recording.id) }.to raise_error
    expect { RecordedTracks.find(@recorded_track.id) }.to raise_error
  end

  it "should allow a user to claim a recording" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "name", "description", @genre, true)
    @recording.reload
    @recording.users.length.should == 1
    @recording.users.first.should == @user
    @user.recordings.length.should == 1
    @user.recordings.first.should == @recording
    @recording.claimed_recordings.length.should == 1
    @claimed_recording = @recording.claimed_recordings.first
    @claimed_recording.name.should == "name"
    @claimed_recording.description.should == "description"
    @claimed_recording.genre.should == @genre
    @claimed_recording.is_public.should == true
    @claimed_recording.upload_to_youtube.should == false
  end

  it "should fail if a user who was not in the session claims a recording" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    user2 = FactoryGirl.create(:user)
    expect { @recording.claim(user2, "name", "description", @genre, true) }.to raise_error
  end

  it "should allow editing metadata for claimed recordings" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @claimed_recording = @recording.claim(@user, "name", "description", @genre, true)
    @genre2 = FactoryGirl.create(:genre)
    @claimed_recording.update_fields(@user, :name => "name2", :description => "description2", :genre => @genre2.id, :is_public => false)
    @claimed_recording.reload
    @claimed_recording.name.should == "name2"
    @claimed_recording.description.should == "description2"
    @claimed_recording.genre.should == @genre2
    @claimed_recording.is_public.should == false
    @claimed_recording.upload_to_youtube.should == false
  end

  it "should only allow the owner to edit a claimed recording" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @claimed_recording = @recording.claim(@user, "name", "description", @genre, true)
    @user2 = FactoryGirl.create(:user)
    expect { @claimed_recording.update_fields(@user2, "name2") }.to raise_error
  end

  it "should record the duration of the recording properly" do
    @recording = Recording.start(@music_session, @user)
    @recording.duration.should be_nil
    @recording.stop
    @recording.reload
    @recording.duration.should_not be_nil
    # Note: it will be 0 since this was fast. You can see something non-zero by just
    # inserting a sleep here.
    # puts @recording.duration
  end

  it "should only destroy a single claimed_recording if there are more than one" do
    @user2 = FactoryGirl.create(:user)
    @connection2 = FactoryGirl.create(:connection, :user => @user2)
    @track = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument)
    # @music_session.connections << @connection2
    @music_session.save
    @connection2.join_the_session(@music_session, true, nil, @user2, 10)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @claimed_recording = @recording.claim(@user, "name", "description", @genre, true)
    expect { @claimed_recordign.discard(@user2) }.to raise_error
    @claimed_recording = @recording.claim(@user2, "name2", "description2", @genre, true)
    @claimed_recording.discard(@user2)
    @claimed_recording.reload
    @claimed_recording.discarded.should == true
    @recording.recorded_tracks_for_user(@user2)[0].discard.should == true
    @recording.reload
    @recording.claimed_recordings.length.should == 2
    @recording.all_discarded.should == false
  end

  it "should set youtube flag" do

    @connection.join_the_session(@music_session, true, nil, @user, 10)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "name", "description", @genre, true, true)

    @recording.reload
    @recording.users.length.should == 1
    @recording.users.first.should == @user
    @user.recordings.length.should == 1
    @user.recordings.first.should == @recording
    @recording.claimed_recordings.length.should == 1
    @claimed_recording = @recording.claimed_recordings.first
    @claimed_recording.name.should == "name"
    @claimed_recording.description.should == "description"
    @claimed_recording.genre.should == @genre
    @claimed_recording.is_public.should == true
    @claimed_recording.upload_to_youtube.should == true
  end

  it "should destroy the entire recording if there was only one claimed_recording which is discarded" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @claimed_recording = @recording.claim(@user, "name", "description", @genre, true)
    @claimed_recording.discard(@user)
    @claimed_recording.reload
    @claimed_recording.discarded.should == true
    @claimed_recording.recording.all_discarded.should == true
    @recording.recorded_tracks_for_user(@user)[0].discard.should == true
  end

  it "should use the since parameter when restricting uploads" do
    stub_const("APP_CONFIG", app_config)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)
    uploads = Recording.list_uploads(@user)
    uploads["uploads"].length.should == 2 # recorded_track and stream_mix
    Recording.list_uploads(@user, 10, uploads["next"])["uploads"].length.should == 0
  end


  it "should not consider deleted recordings" do
    stub_const("APP_CONFIG", app_config)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)
    @recording.mark_delete
    uploads = Recording.list_uploads(@user)
    uploads["uploads"].length.should == 0
  end

  it "should return a download only if claimed" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)
    downloads = Recording.list_downloads(@user)
    downloads["downloads"].length.should == 0
    @recorded_track = RecordedTrack.where(:recording_id => @recording.id)[0]
    @recorded_track.update_attribute(:fully_uploaded, true)
    downloads = Recording.list_downloads(@user)
    downloads["downloads"].length.should == 1
  end

  it "should not return a download if recording is deleted" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)
    downloads = Recording.list_downloads(@user)
    downloads["downloads"].length.should == 0
    @recorded_track = RecordedTrack.where(:recording_id => @recording.id)[0]
    @recorded_track.update_attribute(:fully_uploaded, true)
    @recording.mark_delete
    downloads = Recording.list_downloads(@user)
    downloads["downloads"].length.should == 0
  end

  it "should mark first_recording_at" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.claim(@user, "Recording", "Recording Description", Genre.first, true)
    @user.first_recording_at.should be_nil
    @user.reload
    @user.first_recording_at.should_not be_nil
  end

  describe "chance for everyone to keep or discard" do
    before(:each) do
      @user2 = FactoryGirl.create(:user)
      @connection2 = FactoryGirl.create(:connection, :user => @user2, :music_session => @music_session)
      @track2 = FactoryGirl.create(:track, :connection => @connection2, :instrument => @instrument)

      @recording = Recording.start(@music_session, @user)
      @recording.stop
      @recording.reload
    end

    it "no one votes" do
      @recording.all_discarded.should be_false
      @recording2 = Recording.start(@music_session, @user)
      @recording2.errors.any?.should be_true
      @recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED]
    end

    it "only one discards" do
      @recording.discard(@user)
      @recording.all_discarded.should be_false
      @recording2 = Recording.start(@music_session, @user)
      @recording2.errors.any?.should be_true
      @recording2.errors[:music_session].should == [ValidationMessages::PREVIOUS_RECORDING_STILL_BEING_FINALIZED]
    end

    it "everyone discards" do
      @recording.discard(@user)
      @recording.discard(@user2)
      @recording.all_discarded.should be_true
      @recording2 = Recording.start(@music_session, @user)
      @recording2.errors.any?.should be_false
    end

    it "one discards, the other leaves the session" do
      @recording.discard(@user)
      @recording.all_discarded.should be_false
      @connection2.delete
      @recording2 = Recording.start(@music_session, @user2)
      @recording2.errors.any?.should be_false
    end
  end


  it "set video from source" do
    @video_source = FactoryGirl.create(:video_source, :connection => @connection)

    @music_session.is_recording?.should be_false
    @recording = Recording.start(@music_session, @user)
    @music_session.reload
    @music_session.recordings[0].should == @recording
    @recording.owner_id.should == @user.id

    @recorded_videos = RecordedVideo.where(:recording_id => @recording.id)
    @recorded_videos.should have(1).items
    @recorded_videos[0].client_video_source_id.should eq(@video_source.client_video_source_id)
  end

  it "should include video when listing uploads" do
    @video_source = FactoryGirl.create(:video_source, :connection => @connection)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)

    @backing_track = FactoryGirl.create(:backing_track, :connection => @connection)

    # We should have 2 items; a track and a video:
    uploads = Recording.list_uploads(@user)
    uploads["uploads"].should have(3).items
    uploads["uploads"][0][:type].should eq("stream_mix")
    uploads["uploads"][1][:type].should eq("recorded_track")
    uploads["uploads"][2][:type].should eq("recorded_video")
    uploads["uploads"][1].should include(:client_track_id)
    uploads["uploads"][2].should include(:client_video_source_id)

    # Next page should have nothing:
    uploads = Recording.list_uploads(@user, 10, uploads["next"])
    uploads["uploads"].should have(0).items
  end

  it "should paginate with video" do
    @video_source = FactoryGirl.create(:video_source, :connection => @connection)
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)

    # Limit to 1, so we can test pagination:
    uploads = Recording.list_uploads(@user, 1)
    uploads["uploads"].should have(1).items # First page
    uploads["uploads"][0][:type].should == 'stream_mix'

    # Second page:
    uploads = Recording.list_uploads(@user, 1, uploads["next"])
    uploads["uploads"].should have(1).items
    uploads["uploads"][0][:type].should == 'recorded_track'

    # Last page (should be empty):
    uploads = Recording.list_uploads(@user, 1, uploads["next"])
    uploads["uploads"].should have(1).items
    uploads["uploads"][0][:type].should == 'recorded_video'

    uploads = Recording.list_uploads(@user, 1, uploads["next"])
    uploads["uploads"].should have(0).items
  end

  it "should only retrieve tracks and videos from user" do
    user2 = FactoryGirl.create(:user) # in the jam session
    music_session2 = FactoryGirl.create(:active_music_session, :creator => @user, :musician_access => true)
    music_session_member2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session, :ip_address => "2.2.2.2", :client_id => "2")
    connection2 = FactoryGirl.create(:connection, :user => user2, :music_session => @music_session)
    track2 = FactoryGirl.create(:track, :connection => connection2, :instrument => @instrument)

    video_source = FactoryGirl.create(:video_source, :connection => @connection)
    video_source2 = FactoryGirl.create(:video_source, :connection => connection2)

    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)

    # We should have 3 items; a track and a video:
    uploads = Recording.list_uploads(@user)
    uploads["uploads"].should have(3).items
    uploads["uploads"][0][:type].should eq("stream_mix")
    uploads["uploads"][1][:type].should eq("recorded_track")
    uploads["uploads"][2][:type].should eq("recorded_video")
    uploads["uploads"][1].should include(:client_track_id)
    uploads["uploads"][2].should include(:client_video_source_id)

    uploads["uploads"][1][:client_track_id].should eq(@track.client_track_id)
    uploads["uploads"][2][:client_video_source_id].should eq(video_source.client_video_source_id)

    # Next page should have nothing:
    uploads = Recording.list_uploads(@user, 10, uploads["next"])
    uploads["uploads"].should have(0).items

    # List uploads for user2.  We should have 2 items; a track and a video:
    # The track and video source IDs should be different than above:
    uploads = Recording.list_uploads(user2)
    uploads["uploads"].should have(3).items
    uploads["uploads"][0][:type].should eq("stream_mix")
    uploads["uploads"][1][:type].should eq("recorded_track")
    uploads["uploads"][2][:type].should eq("recorded_video")
    uploads["uploads"][1].should include(:client_track_id)
    uploads["uploads"][2].should include(:client_video_source_id)
    uploads["uploads"][1][:client_track_id].should eq(track2.client_track_id)
    uploads["uploads"][2][:client_video_source_id].should eq(video_source2.client_video_source_id)

    # Next page should have nothing:
    uploads = Recording.list_uploads(user2, 10, uploads["next"])
    uploads["uploads"].should have(0).items

  end

  it "stream_mix.fully_uploaded = true removes from list_uploads" do
    @recording = Recording.start(@music_session, @user)
    @recording.stop
    @recording.reload
    @genre = FactoryGirl.create(:genre)
    @recording.claim(@user, "Recording", "Recording Description", @genre, true)

    # We should have 2 items; a track and a quick mix:
    uploads = Recording.list_uploads(@user)
    uploads["uploads"].should have(2).items
    uploads["uploads"][0][:type].should eq("stream_mix")
    uploads["uploads"][1][:type].should eq("recorded_track")

    @recording.quick_mixes[0].fully_uploaded = true
    @recording.quick_mixes[0].save!

    uploads = Recording.list_uploads(@user)
    uploads["uploads"].should have(1).items
    uploads["uploads"][0][:type].should eq("recorded_track")


    @recording.recorded_tracks[0].fully_uploaded = true
    @recording.recorded_tracks[0].save!

    uploads = Recording.list_uploads(@user)
    uploads["uploads"].should have(0).items

  end

  describe "discarded_and_stale" do
    let(:recording1) { FactoryGirl.create(:recording_with_track) }
    let(:track1) { recording1.recorded_tracks[0] }

    it "no results if no recordings" do
      Recording.discarded_and_stale.length.should == 0
    end

    describe "with one recording" do
      before(:each) do
        track1.discard.should be_nil
      end

      describe "that has no votes" do

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0

        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          # and we should find it now...
          stale = Recording.discarded_and_stale
          stale.first.should eq(recording1)
        end

        it "is not readonly" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          # and we should find it now...
          stale = Recording.discarded_and_stale
          stale.first.readonly?.should be_false
        end
      end

      describe "that has discard vote" do

        before(:each) do
          track1.discard = true
          track1.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0

        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          # and we should find it now...
          stale = Recording.discarded_and_stale
          stale.first.should eq(recording1)
        end
      end

      describe "that has keep vote" do

        before(:each) do
          track1.discard = false
          track1.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end

        it "still not found it has an old updated_at time, because it was kept" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          # and still not find it
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end
      end

      describe "that has two tracks, no votes" do

        let(:track2) { FactoryGirl.create(:recorded_track, recording: recording1, user: recording1.owner) }

        before(:each) do
          track1.discard = nil
          track1.save!

          recording1.recorded_tracks << track2
          recording1.save!

          track2.discard = nil
          track2.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0

        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          # and we should find it now...
          stale = Recording.discarded_and_stale
          stale.first.should eq(recording1)
        end
      end
    end

    describe "that has two tracks, two discard" do

      let(:track2) { FactoryGirl.create(:recorded_track, recording: recording1, user: recording1.owner) }

      before(:each) do
        track1.discard = true
        track1.save!

        recording1.recorded_tracks << track2
        recording1.save!

        track2.discard = true
        track2.save!
      end

      it "not found if it has recent updated_at time" do
        stale = Recording.discarded_and_stale
        stale.length.should == 0

      end

      it "found if it has an old updated_at time" do
        # now age the recording
        Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

        # and we should find it now...
        stale = Recording.discarded_and_stale
        stale.first.should eq(recording1)
      end
    end

    describe "that has two tracks, one discard, one keep" do

      let(:track2) { FactoryGirl.create(:recorded_track, recording: recording1, user: recording1.owner) }

      before(:each) do
        track1.discard = true
        track1.save!

        recording1.recorded_tracks << track2
        recording1.save!

        track2.discard = false
        track2.save!
      end

      it "not found if it has recent updated_at time" do
        stale = Recording.discarded_and_stale
        stale.length.should == 0
      end

      it "found if it has an old updated_at time" do
        # now age the recording
        Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

        stale = Recording.discarded_and_stale
        stale.length.should == 0
      end
    end

    describe "that has two tracks, two keeps" do

      let(:track2) { FactoryGirl.create(:recorded_track, recording: recording1, user: recording1.owner) }

      before(:each) do
        track1.discard = false
        track1.save!

        recording1.recorded_tracks << track2
        recording1.save!

        track2.discard = false
        track2.save!
      end

      it "not found if it has recent updated_at time" do
        stale = Recording.discarded_and_stale
        stale.length.should == 0
      end

      it "found if it has an old updated_at time" do
        # now age the recording
        Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

        stale = Recording.discarded_and_stale
        stale.length.should == 0
      end
    end

    describe "two recordings" do
      let(:recording2) { FactoryGirl.create(:recording_with_track) }
      let(:track2) { recording2.recorded_tracks[0] }

      describe "both discard" do

        before(:each) do
          track1.discard = true
          track1.save!

          track2.discard = true
          track2.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 1
          stale.first.should eq(recording1)

          Recording.where(:id => recording2.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 2
        end
      end

      describe "both keep" do

        before(:each) do
          track1.discard = false
          track1.save!

          track2.discard = false
          track2.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 0

          Recording.where(:id => recording2.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end
      end

      describe "one keep, one discard" do

        before(:each) do
          track1.discard = false
          track1.save!

          track2.discard = true
          track2.save!
        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 0

          Recording.where(:id => recording2.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 1
          stale.first.should eq(recording2)
        end
      end

      describe "two keeps, two discards" do

        let(:track1_2) { FactoryGirl.create(:recorded_track, recording: recording1, user: recording1.owner) }
        let(:track2_2) { FactoryGirl.create(:recorded_track, recording: recording2, user: recording1.owner) }

        before(:each) do
          track1.discard = false
          track1.save!
          recording1.recorded_tracks << track1_2
          recording1.save!
          track1_2.discard = false
          track1_2.save!

          track2.discard = true
          track2.save!
          recording2.recorded_tracks << track2_2
          recording2.save!
          track2_2.discard = true
          track2_2.save!

        end

        it "not found if it has recent updated_at time" do
          stale = Recording.discarded_and_stale
          stale.length.should == 0
        end

        it "found if it has an old updated_at time" do
          # now age the recording
          Recording.where(:id => recording1.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 0

          Recording.where(:id => recording2.id).update_all(:updated_at => (APP_CONFIG.recordings_stale_time + 1).days.ago)

          stale = Recording.discarded_and_stale
          stale.length.should == 1
          stale.first.should eq(recording2)
        end
      end
    end
  end

  describe "delete" do
    let(:mix) { FactoryGirl.create(:mix) }
    let(:recording) { mix.recording }

    before(:each) do

    end

    it "success" do
      FactoryGirl.create(:quick_mix, user: recording.owner, recording: recording, autowire: false)
      FactoryGirl.create(:recording_comment, recording: recording, user: recording.owner)
      FactoryGirl.create(:recording_like, recording: recording, claimed_recording: recording.claimed_recordings.first, favorite: true)
      FactoryGirl.create(:playable_play, playable_id: recording.id, playable_type: 'JamRuby::Recording')
      FactoryGirl.create(:recorded_video, user: recording.owner, recording: recording)
      recording.reload
      recording.claimed_recordings.length.should > 0
      recording.mixes.length.should > 0
      recording.quick_mixes.length.should > 0
      recording.recorded_tracks.length.should > 0
      recording.comments.length.should > 0
      recording.likes.length.should > 0
      recording.plays.length.should > 0
      recording.recorded_videos.length.should > 0
      recording.feed.should_not be_nil

      claimed_recording = recording.claimed_recordings.first
      quick_mix = recording.quick_mixes.first
      track = recording.recorded_tracks.first
      comment = recording.comments.first
      like = recording.likes.first
      play = recording.plays.first
      feed = recording.feed
      video = recording.recorded_videos.first

      recording.mark_delete

      ClaimedRecording.find_by_id(claimed_recording.id).should_not be_nil
      Mix.find_by_id(mix.id).should_not be_nil
      QuickMix.find_by_id(quick_mix.id).should_not be_nil
      RecordedTrack.find_by_id(track.id).should_not be_nil
      RecordingComment.find_by_id(comment.id).should_not be_nil
      PlayablePlay.find_by_id(play.id).should_not be_nil
      RecordingLiker.find_by_id(like.id).should_not be_nil
      Feed.find_by_id(feed.id).should_not be_nil
      RecordedVideo.find_by_id(video.id).should_not be_nil
    end
  end

  describe "add_timeline" do

    let!(:recorded_jam_track_track) { FactoryGirl.create(:recorded_jam_track_track) }
    let(:recording) { recorded_jam_track_track.recording }
    let(:timeline_data) { {"sample" => "data"} }
    let(:good_timeline) { {
        "global" => {"recording_start_time" => 0, "jam_track_play_start_time" => 0, "jam_track_recording_start_play_offset" => 0},
        "tracks" => [
            {
                "id" => recorded_jam_track_track.jam_track_track.id,
                "timeline" => timeline_data,
                "type" => "jam_track"
            }
        ]
    }
    }

    it "applies timeline data correctly" do
      recording.add_timeline good_timeline
      recorded_jam_track_track.reload
      recorded_jam_track_track.timeline.should eq(timeline_data)
    end

    it "fails if no tracks data" do
      expect { recording.add_timeline({}) }.to raise_error(JamRuby::JamArgumentError)
    end
  end
end


