require 'spec_helper'

# user progression is achieved by different aspects of the code working together in a cross-cutting fashion.
# due to this, it's nice to have a single place where all the parts of user progression are tested
# https://jamkazam.atlassian.net/wiki/pages/viewpage.action?pageId=3375145

describe "User Progression", :type => :api do

  subject { page }

  def login(user)
    post '/sessions', "session[email]" => user.email, "session[password]" => user.password
    rack_mock_session.cookie_jar["remember_token"].should == user.remember_token
  end

  describe "user progression" do
    let(:user) { FactoryGirl.create(:user) }
    let(:defopts) { { :description => "a session", :fan_chat => true, :fan_access => true, :approval_required => false, :genres => ["classical"], :musician_access => true, :tracks => [{"instrument_id" => "electric guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}], :legal_terms => true, :intellectual_property => true} }

    before do
      login(user)
    end

    it "downloaded_client" do
      user.first_downloaded_client_at.should be_nil
      post "/api/users/progression/downloaded_client"
      last_response.status.should eql(200)
      JSON.parse(last_response.body).should eql({ })
      user.reload
      user.first_downloaded_client_at.should_not be_nil
    end

    it "downloaded_client twice" do
      post "/api/users/progression/downloaded_client"
      user.reload
      first = user.first_downloaded_client_at
      post "/api/users/progression/downloaded_client"
      user.reload
      user.first_downloaded_client_at.should == first
    end

    it "qualified gear" do
      connection = FactoryGirl.create(:connection, user: user, ip_address: '127.0.0.1', locidispid: locidispid_from_ip('127.0.0.1'))

      user.first_certified_gear_at.should be_nil
      user.last_jam_addr.should be_nil
      user.last_jam_locidispid.should be_nil
      post "/api/users/progression/certified_gear.json", { :success => true, client_id: connection.client_id}.to_json,  "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(200)
      JSON.parse(last_response.body).should eql({ })
      user.reload
      user.first_certified_gear_at.should_not be_nil
      user.last_failed_certified_gear_at.should be_nil
      user.last_failed_certified_gear_reason.should be_nil
      user.last_jam_addr.should == ip_address_to_int('127.0.0.1')
      user.last_jam_updated_reason.should == User::JAM_REASON_FTUE
      user.last_jam_updated_at.should_not be_nil
      user.last_jam_locidispid.should == locidispid_from_ip('127.0.0.1')
    end

    it "failed qualified gear" do
      user.first_certified_gear_at.should be_nil
      post "/api/users/progression/certified_gear.json", { :success => false, :reason => "latency=30"}.to_json,  "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(200)
      JSON.parse(last_response.body).should eql({ })
      user.reload
      user.first_certified_gear_at.should be_nil
      user.last_failed_certified_gear_at.should_not be_nil
      user.last_failed_certified_gear_reason.should == "latency=30"
    end


    it "social promoted" do
      user.first_social_promoted_at.should be_nil
      post "/api/users/progression/social_promoted"
      last_response.status.should eql(200)
      JSON.parse(last_response.body).should eql({ })
      user.reload
      user.first_social_promoted_at.should_not be_nil
    end

    it "joined any session" do
      pending
      user.first_music_session_at.should be_nil
      client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1.1")

      client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1")
      post '/api/sessions.json', defopts.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      # now fetch it's data
      music_session = JSON.parse(last_response.body)
      post "/api/sessions/#{music_session["id"]}/participants.json", defpart.merge({ :client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      last_response.status.should eql(201)
      user.reload
      user.first_music_session_at.should_not be_nil
    end

    it "ran client" do
      user.first_ran_client_at.should be_nil
      # change user-agent to look like the real client, and see ran_client flag set
      post '/sessions', {"session[email]" => user.email, "session[password]" => user.password}, { "HTTP_USER_AGENT" => " JamKazam " }
      user.reload
      user.first_ran_client_at.should_not be_nil
    end

    it "real session" do
      pending
      # to make a real session, we need a session at least 15 minutes long and containting 3 concurrent users

      user2 = FactoryGirl.create(:user)
      user3 = FactoryGirl.create(:user)

      user.first_real_music_session_at.should be_nil
      client = FactoryGirl.create(:connection, :user => user, :ip_address => "1.1.1.1", :client_id => "1_1")
      client2 = FactoryGirl.create(:connection, :user => user2, :ip_address => "1.1.1.2", :client_id => "1_2")
      client3 = FactoryGirl.create(:connection, :user => user3, :ip_address => "1.1.1.3", :client_id => "1_3")

      post '/api/sessions.json', defopts.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      # now fetch it's data
      music_session = JSON.parse(last_response.body)
      post "/api/sessions/#{music_session["id"]}/participants.json", defpart.merge({ :client_id => client.client_id}).to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      music_session = JSON.parse(last_response.body)

      login(user2)
      post "/api/sessions/#{music_session["id"]}/participants.json", {  :client_id => client2.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      login(user3)
      post "/api/sessions/#{music_session["id"]}/participants.json", {  :client_id => client3.client_id, :as_musician => true, :tracks => [{"instrument_id" => "bass guitar", "sound" => "mono", "client_track_id" => "client_track_guid"}]}.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(201)

      # instrument the created_at of the music_history field to be at the beginning of time, so that we cross the 15 minute threshold of a 'real session
      history1 = MusicSessionUserHistory.where(:user_id => user.id, :music_session_id => music_session["id"]).first
      history2 = MusicSessionUserHistory.where(:user_id => user2.id, :music_session_id => music_session["id"]).first
      history3 = MusicSessionUserHistory.where(:user_id => user3.id, :music_session_id => music_session["id"]).first
      history1.should_not be_nil
      history2.should_not be_nil
      history3.should_not be_nil
      history1.created_at = Time.at(0)
      history2.created_at = Time.at(0)
      history3.created_at = Time.at(0)
      history1.save
      history2.save
      history3.save

      # now log out of the session for all 3 users
      login(user)
      delete "/api/participants/#{client.client_id}.json", '', "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(204)
      login(user2)
      delete "/api/participants/#{client2.client_id}.json", '', "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(204)
      login(user3)
      delete "/api/participants/#{client3.client_id}.json", '', "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(204)

      user.reload
      user2.reload
      user3.reload
      user.first_real_music_session_at.should_not be_nil
      user2.first_real_music_session_at.should_not be_nil
      user3.first_real_music_session_at.should_not be_nil
    end

    it "invites user" do
      user.first_invited_at.should be_nil
      post '/api/invited_users.json', {:emails => ['tester@jamkazam.com'], :note => "please join"}.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should eql(200)
      user.reload
      user.first_invited_at.should_not be_nil
    end

    it "good session" do
      user = FactoryGirl.create(:user)
      user.first_good_music_session_at.should be_nil

      client = FactoryGirl.create(:connection, :user => user)
      music_session = FactoryGirl.create(:active_music_session, :creator => user, :description => "My Session")
      msuh = FactoryGirl.create(:music_session_user_history, :music_session_id => music_session.id, :client_id => client.client_id, :user_id => user.id)
      expect(msuh).to_not eq(nil)
      login(user)
      post "/api/participant_histories/#{msuh.client_id}/rating.json", { :rating => 1 }.to_json, "CONTENT_TYPE" => "application/json"

      user.reload
      user.first_good_music_session_at.should_not be_nil
    end
  end

end
