require 'spec_helper'

describe Band do

  let(:user)      { FactoryGirl.create(:user) }
  let(:user2)     { FactoryGirl.create(:user) }
  let(:fan)       { FactoryGirl.create(:fan) }
  let(:band)      { FactoryGirl.create(:band) }
  let(:band_in_austin) { FactoryGirl.create(:band, country: 'US', state: 'TX', city: 'Austin')}
  let(:new_band)  { FactoryGirl.build(:band) }
  let(:band_params) {
    {
      name: "The Band",
      biography: "Biography",
      city: 'Austin',
      state: 'TX',
      country: 'US',
      genres: ['country']
    }
  }

  let(:band_params_no_genre) {
    {
      name: "The Band",
      biography: "Biography",
      city: 'Austin',
      state: 'TX',
      country: 'US',
      validate_genres:true
    }
  }

  describe 'with instruments' do
    it 'builds with instruments' do
      band.musician_instruments << FactoryGirl.build(:musician_instrument, player: band)
      band.musician_instruments.should have(1).items
      band.instruments.should have(1).items
    end

    it 'creates with instruments' do
      FactoryGirl.create(:musician_instrument, player: band)
      band.reload
      band.musician_instruments.should have(1).items
      band.instruments.should have(1).items
    end
  end

  describe 'website update' do
    it 'should have http prefix on website url' do
      band.website = 'example.com'
      band.save!
      expect(band.website).to match(/^http:\/\/example.com$/)
    end
  end

  describe 'band validations' do
    it "minimum genres" do
      new_band.save.should be_false
      new_band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]

      new_band.genres = [Genre.first]
      new_band.save.should be_true
    end

    it "maximum genres" do
      new_band.genres = Genre.limit(4)
      new_band.save.should be_false
      new_band.errors[:genres].should == [ValidationMessages::BAND_GENRE_LIMIT_EXCEEDED]
    end
  end

  describe "save" do
    it "genres validate" do
       band=Band.save(user, band_params_no_genre)
       band.errors.any?.should be_true
       band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]

       band = Band.save(user, band_params)
       band.errors.any?.should be_false

       # Save again without a genre and make sure we get an error:
       p = band_params_no_genre.clone
       p[:id] = band.id
       band = Band.save(user, p)
       band.errors.any?.should be_true
       band.errors[:genres].should == [ValidationMessages::BAND_GENRE_MINIMUM_NOT_MET]
    end

    it "can succeed" do
      band = Band.save(user, band_params)
      band.errors.any?.should be_false
      band.name.should == band_params[:name]
      band.biography.should == band_params[:biography]
      band.genres.should == [Genre.find(band_params[:genres][0])]
      band.city.should == band_params[:city]
      band.state.should == band_params[:state]
      band.country.should == band_params[:country]
    end

    it "saves current interests" do
      parms = band_params
      parms[:paid_gigs]=true
      parms[:free_gigs]=false
      parms[:hourly_rate]=5000
      parms[:gig_minimum]=30000
      parms[:add_new_members]=true
      parms[:touring_option]=false
      parms[:band_type]="virtual"
      parms[:band_status]="amateur"
      parms[:concert_count]=3

      band = Band.save(user, parms)
      band.errors.any?.should be_false

      band.paid_gigs.should == true
      band.free_gigs.should == false
      band.hourly_rate.should == 5000
      parms[:gig_minimum]=30000
      band.add_new_members.should == true
      band.touring_option.should == false
      band.band_type.should == "virtual"
      band.band_status.should == "amateur"
      band.concert_count.should == 3
    end


    it "ensures user is a musician" do
      expect{ Band.save(fan, band_params) }.to raise_error("must be a musician")
    end

    it "can update" do
      band = Band.save(user, band_params)
      band.errors.any?.should be_false
      band_params[:id] = band.id
      band_params[:name] = "changed name"
      band = Band.save(user, band_params)
      band.errors.any?.should be_false
      Band.find(band.id).name.should == band_params[:name]
    end

    it "stops non-members from updating" do
      band = Band.save(user, band_params)
      band.errors.any?.should be_false
      band_params[:id] = band.id
      band_params[:name] = "changed name"
      expect{ Band.save(user2, band_params) }.to raise_error(ValidationMessages::USER_NOT_BAND_MEMBER_VALIDATION_ERROR)
    end
  end

  describe "validate" do
    it "can pass" do
      band = Band.build_band(user, band_params)
      band.valid?.should be_true
    end

    it "can fail" do
      band_params[:name] = nil
      band = Band.build_band(user, band_params)
      band.valid?.should be_false
      band.errors[:name].should == ["can't be blank"]
    end
  end

  describe "after_maxmind_import" do

    before(:each) do
      create_phony_database
    end

    after(:all) do
      create_phony_database
    end

    it "updates to non-null after import if matching location is available" do
      band_in_austin.lat.should be_nil
      band_in_austin.lng.should be_nil
      Band.after_maxmind_import(false)
      band_in_austin.reload
      band_in_austin.lat.should == 30.2076
      band_in_austin.lng.should == -97.8587
    end

    it "updates to non-null after import if matching location is available, with two matching geoip locations" do
      band_in_austin.lat.should be_nil
      band_in_austin.lng.should be_nil
      # change the dallas entry to austin, to make two austin entries
      GeoIpLocations.connection.execute("UPDATE geoiplocations SET city = 'Austin', region = 'TX', countrycode ='US' WHERE city = 'Dallas' AND region = 'TX' and countrycode = 'US'").check
      Band.after_maxmind_import(false)
      band_in_austin.reload

      # you don't know which GeoIpLocation it'll be.  So we need to check both
      [30.2076, 32.7825].include?(band_in_austin.lat).should be_true
      [-97.8587, -96.8207].include?(band_in_austin.lng).should be_true
    end

    it "updates to null if no matching location available" do
      band_in_austin.city = 'Blibbity'
      band_in_austin.save!
      # change the dallas entry to austin, to make two austin entries
      GeoIpLocations.connection.execute("UPDATE geoiplocations SET city = 'Austin', region = 'TX', countrycode ='US' WHERE city = 'Dallas' AND region = 'TX' and countrycode = 'US'").check
      Band.after_maxmind_import(false)
      band_in_austin.reload
      band_in_austin.lat.should be_nil
      band_in_austin.lng.should be_nil
    end
  end

  describe "recent history" do
    it "should only retrieve recordings with a claimed recording" do
      user = FactoryGirl.create(:user)
      band = FactoryGirl.create(:band)
      band.users << user
      band.save!

      claimed_recording = FactoryGirl.create(:claimed_recording, :user => user)
      claimed_recording.recording.owner = user
      claimed_recording.recording.band = band
      claimed_recording.recording.save!

      recording = FactoryGirl.create(:recording, :owner => user, :band => band)

      Recording.where(:owner_id => user.id).size.should == 2
      Recording.where(:band_id => band.id).size.should == 2

      history = band.recent_history(nil, nil)
      history.size.should == 1
      history.first.id.should == claimed_recording.recording.id

      # exclude the claimed recording
      history = band.recent_history(nil, claimed_recording.id)
      history.size.should == 0
    end
  end
end
