require 'spec_helper'

describe Track do

  let (:user) {FactoryGirl.create(:user) }
  let (:music_session) { FactoryGirl.create(:active_music_session, :creator => user)}
  let (:connection) { FactoryGirl.create(:connection, :user => user, :music_session => music_session) }
  let (:track) { FactoryGirl.create(:track, :connection => connection)}
  let (:track2) { FactoryGirl.create(:track, :connection => connection)}
  let (:backing_track) { FactoryGirl.create(:backing_track, :connection => connection)}
  let (:msuh) {FactoryGirl.create(:music_session_user_history, :history => music_session.music_session, :user => user, :client_id => connection.client_id) }
  let (:track_hash) { {:client_track_id => 'client_guid', :sound => 'stereo', :instrument_id => 'drums'} }
  let (:backing_track_hash) { {:client_track_id => 'client_guid', :filename => "blah.wav"} }

  before(:each) do
    msuh.touch
  end

  describe "sync" do
    it "create one track" do
      result = Track.sync(connection.client_id, [track_hash])
      tracks = result[:tracks]
      tracks.length.should == 1
      track = tracks[0]
      track.client_track_id.should == track_hash[:client_track_id]
      track.sound = track_hash[:sound]
      track.instrument.should == Instrument.find('drums')
    end

    it "create two tracks" do
      result = Track.sync(connection.client_id, [track_hash, track_hash])
      tracks = result[:tracks]
      tracks.length.should == 2
      track = tracks[0]
      track.client_track_id.should == track_hash[:client_track_id]
      track.sound = track_hash[:sound]
      track.instrument.should == Instrument.find('drums')
      track = tracks[1]
      track.client_track_id.should == track_hash[:client_track_id]
      track.sound = track_hash[:sound]
      track.instrument.should == Instrument.find('drums')
    end

    it "delete only track" do
      track.id.should_not  be_nil
      connection.tracks.length.should == 1
      result = Track.sync(connection.client_id, [])
      tracks = result[:tracks]
      tracks.length.should == 0
    end

    it "delete one of two tracks using .id to correlate" do

      track.id.should_not be_nil
      track2.id.should_not be_nil
      connection.tracks.length.should == 2
      result = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => 'client_guid_new', :sound => 'mono', :instrument_id => 'drums'}])
      tracks = result[:tracks]
      tracks.length.should == 1
      found = tracks[0]
      found.id.should == track.id
      found.sound.should == 'mono'
      found.client_track_id.should == 'client_guid_new'
    end

    it "delete one of two tracks using .client_track_id to correlate" do

      track.id.should_not be_nil
      track2.id.should_not be_nil
      connection.tracks.length.should == 2
      result = Track.sync(connection.client_id, [{:client_track_id => track.client_track_id, :sound => 'mono', :instrument_id => 'drums'}])
      tracks = result[:tracks]
      tracks.length.should == 1
      found = tracks[0]
      found.id.should == track.id
      found.sound.should == 'mono'
      found.client_track_id.should == track.client_track_id
    end


    it "updates a single track using .id to correlate" do
      track.id.should_not be_nil
      connection.tracks.length.should == 1
      set_updated_at(track, 1.days.ago)
      result = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => 'client_guid_new', :sound => 'mono', :instrument_id => 'drums'}])
      tracks = result[:tracks]
      tracks.length.should == 1
      found = tracks[0]
      found.id.should == track.id
      found.sound.should == 'mono'
      found.client_track_id.should == 'client_guid_new'
      found.updated_at.should_not == track.updated_at
    end

    it "updates a single track using .client_track_id to correlate" do
      track.id.should_not be_nil
      connection.tracks.length.should == 1
      result = Track.sync(connection.client_id, [{:client_track_id => track.client_track_id, :sound => 'mono', :instrument_id => 'drums'}])
      tracks = result[:tracks]
      tracks.length.should == 1
      found = tracks[0]
      found.id.should == track.id
      found.sound.should == 'mono'
      found.client_track_id.should == track.client_track_id
    end

    it "does not touch updated_at when nothing changes" do
      track.id.should_not be_nil
      connection.tracks.length.should == 1
      set_updated_at(track, 1.days.ago)
      result = Track.sync(connection.client_id, [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id, client_resource_id: track.client_resource_id}])
      tracks = result[:tracks]
      tracks.length.should == 1
      found = tracks[0]
      expect(found.id).to eq track.id
      expect(found.updated_at.to_i).to eq track.updated_at.to_i
    end

    describe "backing tracks" do
      it "create one track and one backing track" do
        result = Track.sync(connection.client_id, [track_hash], [backing_track_hash])
        tracks = result[:tracks]
        tracks.length.should == 1
        track = tracks[0]
        track.client_track_id.should == track_hash[:client_track_id]
        track.sound = track_hash[:sound]
        track.instrument.should == Instrument.find('drums')

        backing_tracks = result[:backing_tracks]
        backing_tracks.length.should == 1
        track = backing_tracks[0]
        track.client_track_id.should == backing_track_hash[:client_track_id]
      end

      it "delete only backing_track" do
        track.id.should_not be_nil
        backing_track.id.should_not be_nil
        connection.tracks.length.should == 1
        connection.backing_tracks.length.should == 1
        result = Track.sync(connection.client_id,
                            [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id, client_resource_id: track.client_resource_id}],
                            [])
        tracks = result[:tracks]
        tracks.length.should == 1
        found = tracks[0]
        expect(found.id).to eq track.id
        expect(found.updated_at.to_i).to eq track.updated_at.to_i

        backing_tracks = result[:backing_tracks]
        backing_tracks.length.should == 0
      end

      it "does not touch updated_at when nothing changes" do
        track.id.should_not be_nil
        backing_track.id.should_not be_nil
        connection.tracks.length.should == 1
        set_updated_at(track, 1.days.ago)
        set_updated_at(backing_track, 1.days.ago)
        result = Track.sync(connection.client_id,
                            [{:id => track.id, :client_track_id => track.client_track_id, :sound => track.sound, :instrument_id => track.instrument_id, client_resource_id: track.client_resource_id}],
                            [{:id => backing_track.id, :client_track_id => backing_track.client_track_id, :filename => backing_track.filename, client_resource_id: backing_track.client_resource_id}])
        tracks = result[:tracks]
        tracks.length.should == 1
        found = tracks[0]
        expect(found.id).to eq track.id
        expect(found.updated_at.to_i).to eq track.updated_at.to_i

        backing_tracks = result[:backing_tracks]
        backing_tracks.length.should == 1
        found = backing_tracks[0]
        expect(found.id).to eq backing_track.id
        expect(found.updated_at.to_i).to eq backing_track.updated_at.to_i
      end
    end

    describe "metronome_open" do
      it "sets metronome_open to true" do
        result = Track.sync(connection.client_id, [track_hash], [], true)
        connection.reload
        connection.metronome_open.should be_true
      end

      it "sets metronome_open to false" do
        connection.metronome_open = true
        connection.save!
        result = Track.sync(connection.client_id, [track_hash], [], false)
        connection.reload
        connection.metronome_open.should be_false
      end
    end
  end
end