require 'spec_helper'

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

  subject { page }

  describe "profile" do
    let(:user) { FactoryGirl.create(:user) }
    let(:fan) { FactoryGirl.create(:fan) }
    let(:band) { FactoryGirl.create(:band) }

    before(:each) do
      UserMailer.deliveries.clear
    end

    def login(email, password, http_code, success)
      # login as fan
      post '/api/auth_session.json', { :email => email, :password => password }.to_json, "CONTENT_TYPE" => 'application/json'
      last_response.status.should == http_code
      JSON.parse(last_response.body).should == { "success" => success }
    end

    def logout
      delete '/api/auth_session.json'
      last_response.status.should == 200
    end

    ########################### USERS #################################
    def get_user(authenticated_user, user = authenticated_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{user.id}.json", "CONTENT_TYPE" => 'application/json'
      last_response.status.should == 200
      return last_response, JSON.parse(last_response.body)
    end

    ########################## LIKES / LIKERS #########################
    def create_user_liking(authenticated_user, source_user, target_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/likings.json", { :user_id => target_user.id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_user_likes(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/likings.json"
      return last_response
    end

    def get_user_likers(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/likers.json"
      return last_response
    end

    def delete_user_like(authenticated_user, source_user, target_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      delete "/api/users/#{source_user.id}/likings/#{target_user.id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def create_band_like(authenticated_user, source_user, target_band)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/likings.json", { :band_id => target_band.id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_likes(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/likings.json"
      return last_response
    end

    def get_band_likers(authenticated_user, source_band)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/bands/#{source_band.id}/likers.json"
      return last_response
    end

    ########################## FOLLOWINGS / FOLLOWERS #########################
    def create_user_following(authenticated_user, source_user, target_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/followings.json", { :user_id => target_user.id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_user_followings(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/followings.json"
      return last_response
    end

    def get_user_followers(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/followers.json"
      return last_response
    end

    def delete_user_following(authenticated_user, source_user, target_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      delete "/api/users/#{source_user.id}/followings/#{target_user.id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def create_band_following(authenticated_user, source_user, target_band)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/followings.json", { :band_id => target_band.id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_followings(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/followings.json"
      return last_response
    end

    def get_band_followers(authenticated_user, source_band)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/bands/#{source_band.id}/followers.json"
      return last_response
    end

    ########################## RECORDINGS #########################
    def create_user_recording(authenticated_user, source_user, description, public, genres)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/recordings.json", { :description => description, :public => public, :genres => genres }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def update_user_recording(authenticated_user, source_user, recording_id, description, public, genres)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/recordings/#{recording_id}.json", { :description => description, :public => public, :genres => genres }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_user_recordings(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/recordings.json"
      return last_response
    end

    def get_user_recording(authenticated_user, source_user, recording_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/recordings/#{recording_id}.json"
      return last_response
    end

    def delete_user_recording(authenticated_user, source_user, recording_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      delete "/api/users/#{source_user.id}/recordings/#{recording_id}.json"
      return last_response
    end

    ########################## FAVORITES #########################
    def create_favorite(authenticated_user, source_user, recording_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/favorites.json", { :recording_id => recording_id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_favorites(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/favorites.json"
      return last_response
    end

    def delete_favorite(authenticated_user, source_user, recording_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      delete "/api/users/#{source_user.id}/favorites/#{recording_id}.json"
    end

    ########################## FRIENDS #########################
    def create_friend_request(authenticated_user, source_user, target_user, message)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/friend_requests.json", { :friend_id => target_user.id, :message => message }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def update_friend_request(authenticated_user, source_user, friend_request_id, status)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/friend_requests/#{friend_request_id}.json", { :status => status }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_friend_requests(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/friend_requests.json"
      return last_response
    end

    def get_friends(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/friends.json"
      return last_response
    end

    def delete_friend(authenticated_user, source_user, target_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      delete "/api/users/#{source_user.id}/friends/#{target_user.id}.json"
    end

    ################################ BANDS ##############################
    def get_user_bands(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/bands.json"
      return last_response
    end

    ########################## BAND INVITATIONS #########################
    def create_band_invitation(authenticated_user, band_id, user_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/bands/#{band_id}/invitations.json", { :band_id => band_id, :user_id => user_id }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def update_band_invitation(authenticated_user, source_user, invitation_id, accepted)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      post "/api/users/#{source_user.id}/band_invitations/#{invitation_id}.json", { :accepted => accepted }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_invitations(authenticated_user, source_user)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/band_invitations.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_invitation(authenticated_user, source_user, invitation_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/users/#{source_user.id}/band_invitations/#{invitation_id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def get_band_details(authenticated_user, band_id)
      login(authenticated_user.email, authenticated_user.password, 200, true)
      get "/api/bands/#{band_id}.json", "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def create_complete(signup_user, options={})
      post "/api/users/complete/#{signup_user.signup_token}.json", options.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    #################### ACCOUNT SETTINGS ###########################
    def begin_update_email(authenticated_user, update_email, validation_password, login = true)
      login(authenticated_user.email, authenticated_user.password, 200, true) if login
      post "/api/users/#{authenticated_user.id}/update_email.json",  { :update_email => update_email, :current_password => validation_password }.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end

    def finalize_update_email(update_email_token)
      post "/api/users/update_email/#{update_email_token}.json", {}.to_json, "CONTENT_TYPE" => 'application/json'
      return last_response
    end


    context "when accessing as unauthenticated user" do

      it "should allow successful login" do
        # can't access most apis; not logged in yet!'
        get '/api/users.json',  "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 403

        # login
        login(user.email, user.password, 200, true)

        # can now login
        get '/api/users.json',  "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 200

        # log back out
        delete '/api/auth_session.json',  "CONTENT_TYPE" => 'application/json'

        # can't access most apis; not logged in yet!'
        get '/api/users.json',  "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 403

      end

      it "should deny bad login" do
        # login
        login("nothing", "mur", 404, false)

        # can't access most apis; not logged in yet!'
        get '/api/users.json',  "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 403
      end
    end

    context "when accessing as authenticated user" do
      # log in a valid user
      it "should allow user updates" do

        # login as fan
        login(fan.email, fan.password, 200, true)

        # update the user's first name and musician flag, and specify one instrument to be a musician
        post "/api/users/#{fan.id}.json", { :first_name => "Brian", :musician => true, :instruments => [ { :instrument_id=>"electric guitar", :proficiency_level => '1', :priority=>0 }] }.to_json, "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 200

        # get the user's details
        last_response, response = get_user(fan, fan)
        last_response.status.should == 200
        updated_user = JSON.parse(last_response.body)
        updated_user["musician"].should be true
        updated_user["first_name"].should == "Brian"
      end

      ###################### LIKERS / LIKES ########################
      it "should allow user to like user" do
        # create user like
        last_response = create_user_liking(user, user, fan)
        last_response.status.should == 201

        # get likes
        last_response = get_user_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 1
        likes[0]["id"].should == fan.id

        # get likers for other side of above like (fan)
        last_response = get_user_likers(fan, fan)
        last_response.status.should == 200
        likers = JSON.parse(last_response.body)
        likers.size.should == 1
        likers[0]["id"].should == user.id
      end

      it "should allow user to like band" do
        # create band like
        last_response = create_band_like(user, user, band)
        last_response.status.should == 201

        # get band likes
        last_response = get_band_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 1
        likes[0]["id"].should == band.id

        # get likers for band
        last_response = get_band_likers(user, band)
        last_response.status.should == 200
        likers = JSON.parse(last_response.body)
        likers.size.should == 1
        likers[0]["id"].should == user.id
      end

      it "should not allow user to create like for another user" do
        dummy_user = FactoryGirl.create(:user)
        last_response = create_user_liking(user, dummy_user, fan)
        last_response.status.should == 403
      end

      it "should allow user to delete like" do
        last_response = create_user_liking(user, user, fan)
        last_response.status.should == 201

        # get likes
        last_response = get_user_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 1
        likes[0]["id"].should == fan.id

        # delete like
        last_response = delete_user_like(user, user, fan)
        last_response.status.should == 204

        # get likes
        last_response = get_user_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 0
      end

      it "should not allow user to delete like of another user" do
        # create user like
        last_response = create_user_liking(user, user, fan)
        last_response.status.should == 201

        # get likes
        last_response = get_user_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 1
        likes[0]["id"].should == fan.id

        # attempt to delete like of another user
        last_response = delete_user_like(fan, user, fan)
        last_response.status.should == 403

        # get likes
        last_response = get_user_likes(user, user)
        last_response.status.should == 200
        likes = JSON.parse(last_response.body)
        likes.size.should == 1
      end

      ###################### FOLLOWERS / FOLLOWINGS ########################
      it "should allow user to follow user" do
        # create user following
        last_response = create_user_following(user, user, fan)
        last_response.status.should == 201

        # get followings
        last_response = get_user_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 1
        followings[0]["id"].should == fan.id

        # get followers for other side of above following (fan)
        last_response = get_user_followers(fan, fan)
        last_response.status.should == 200
        followers = JSON.parse(last_response.body)
        followers.size.should == 1
        followers[0]["id"].should == user.id
      end

      it "should allow user to follow band" do
        # create band following
        last_response = create_band_following(user, user, band)
        last_response.status.should == 201

        # get band followings
        last_response = get_band_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 1
        followings[0]["id"].should == band.id

        # get followers for band
        last_response = get_band_followers(user, band)
        last_response.status.should == 200
        followers = JSON.parse(last_response.body)
        followers.size.should == 1
        followers[0]["id"].should == user.id
      end

      it "should not allow user to create following for another user" do
        dummy_user = FactoryGirl.create(:user)
        last_response = create_user_following(user, dummy_user, fan)
        last_response.status.should == 403
      end

      it "should allow user to delete following" do
        last_response = create_user_following(user, user, fan)
        last_response.status.should == 201

        # get followings
        last_response = get_user_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 1
        followings[0]["id"].should == fan.id

        # delete following
        last_response = delete_user_following(user, user, fan)
        last_response.status.should == 204

        # get followings
        last_response = get_user_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 0
      end

      it "should not allow user to delete following of another user" do
        # create user following
        last_response = create_user_following(user, user, fan)
        last_response.status.should == 201

        # get followings
        last_response = get_user_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 1
        followings[0]["id"].should == fan.id

        # attempt to delete following of another user
        last_response = delete_user_following(fan, user, fan)
        last_response.status.should == 403

        # get followings
        last_response = get_user_followings(user, user)
        last_response.status.should == 200
        followings = JSON.parse(last_response.body)
        followings.size.should == 1
      end

      ######################### RECORDINGS ########################
      # it "should allow musician to create recordings" do
      #   # create public recording
      #   public_description = "My Public Recording"
      #   last_response = create_user_recording(user, user, public_description, true, ["african"])
      #   last_response.status.should == 201
      #   recording = JSON.parse(last_response.body)
      #   recording["description"].should == public_description
      #   recording["public"].should == true

      #   # create private recording
      #   private_description = "My Private Recording"
      #   last_response = create_user_recording(user, user, private_description, false, ["rock"])
      #   last_response.status.should == 201

      #   private_recording = JSON.parse(last_response.body)
      #   private_recording["description"].should == private_description
      #   private_recording["public"].should == false
      #   private_recording["genres"].size.should == 1
      #   private_recording["genres"][0]["id"].should == "rock"

      #   # update the second recording's description, public flag, and genre
      #   last_response = update_user_recording(user, user, private_recording["id"], "My Recording 3", true, ["country"])
      #   last_response.status.should == 200
      #   recording = JSON.parse(last_response.body)
      #   recording["description"].should == "My Recording 3"
      #   recording["public"].should == true

      #   # retrieve the recording details again to ensure the change took effect
      #   last_response = get_user_recording(user, user, recording["id"])
      #   last_response.status.should == 200
      #   recording = JSON.parse(last_response.body)
      #   recording["description"].should == "My Recording 3"
      #   recording["public"].should == true
      #   recording["genres"].size.should == 1
      # end

      # it "should not allow fan to create recordings" do
      #   last_response = create_user_recording(fan, fan, "Fan Recording", true, ["african"])
      #   last_response.status.should == 403
      # end

      # it "should allow creator to see public and private recordings in list" do
      #   # create public recording
      #   public_description = "My Public Recording"
      #   last_response = create_user_recording(user, user, public_description, true, ["african"])
      #   last_response.status.should == 201

      #    # create private recording
      #   private_description = "My Private Recording"
      #   last_response = create_user_recording(user, user, private_description, false, ["african"])
      #   last_response.status.should == 201

      #   # get all recordings as creator
      #   last_response = get_user_recordings(user, user)
      #   recordings = JSON.parse(last_response.body)
      #   recordings.size.should == 2
      # end

      # it "should allow creator to see private recording details" do
      #   # create private recording
      #   private_description = "My Private Recording"
      #   last_response = create_user_recording(user, user, private_description, false, ["african"])
      #   last_response.status.should == 201
      #   private_recording = JSON.parse(last_response.body)
      #   private_recording["description"].should == private_description
      #   private_recording["public"].should == false

      #   # attempt to get the private recording as non-creator
      #   last_response = get_user_recording(user, user, private_recording["id"])
      #   last_response.status.should == 200
      # end

      # it "should not allow non-creator to see private recordings in list" do
      #   # create public recording
      #   public_description = "My Public Recording"
      #   last_response = create_user_recording(user, user, public_description, true, ["country"])
      #   last_response.status.should == 201

      #    # create private recording
      #   private_description = "My Private Recording"
      #   last_response = create_user_recording(user, user, private_description, false, ["country"])
      #   last_response.status.should == 201

      #   # get all recordings as non-creator
      #   last_response = get_user_recordings(fan, user)
      #   last_response.status.should == 200

      #   recordings = JSON.parse(last_response.body)
      #   recordings.size.should == 1
      #   recordings[0]["description"].should == public_description
      #   recordings[0]["public"].should == true
      # end

      # it "should not allow non-creator to see private recording details" do
      #   # create private recording
      #   private_description = "My Private Recording"
      #   last_response = create_user_recording(user, user, private_description, false, ["country"])
      #   last_response.status.should == 201
      #   private_recording = JSON.parse(last_response.body)
      #   private_recording["description"].should == private_description
      #   private_recording["public"].should == false

      #   # attempt to get the private recording as non-creator
      #   last_response = get_user_recording(fan, user, private_recording["id"])
      #   last_response.status.should == 403
      # end

      # it "should allow user to create favorites" do
      #   # create recording first
      #   last_response = create_user_recording(user, user, "My Recording", true, ["country"])
      #   last_response.status.should == 201
      #   recording = JSON.parse(last_response.body)

      #   # add favorite
      #   last_response = create_favorite(fan, fan, recording["id"])
      #   last_response.status.should == 201

      #   # get favorites
      #   last_response = get_favorites(fan, fan)
      #   last_response.status.should == 200
      #   favorites = JSON.parse(last_response.body)
      #   favorites.size.should == 1
      #   favorites[0]["recording_id"].should == recording["id"]
      #   favorites[0]["description"].should == "My Recording"
      #   favorites[0]["public"].should == true

      #   # get recording
      #   last_response = get_user_recording(user, user, recording["id"])
      #   last_response.status.should == 200
      #   recording_with_favorite = JSON.parse(last_response.body)
      #   recording_with_favorite["favorite_count"].should == 1
      # end

      # it "should not allow user to create favorite for another user" do
      #   # create recording first
      #   last_response = create_user_recording(user, user, "My Recording", true, ["country"])
      #   last_response.status.should == 201
      #   recording = JSON.parse(last_response.body)

      #   # attempt to add favorite for another user
      #   last_response = create_favorite(fan, user, recording["id"])
      #   last_response.status.should == 403
      # end

      # it "should allow user to delete favorites" do
      #   # create recording first
      #   last_response = create_user_recording(user, user, "My Recording", true, ["country"])
      #   last_response.status.should == 201
      #   recording = JSON.parse(last_response.body)

      #   # delete favorite
      #   last_response = delete_favorite(user, user, recording["id"])
      #   last_response.status.should == 204

      #   # get favorites
      #   last_response = get_favorites(user, user)
      #   last_response.status.should == 200
      #   favorites = JSON.parse(last_response.body)
      #   favorites.size.should == 0
      # end

      # it "should not allow user to delete another user's favorites" do
      #   # create recording first
      #   last_response = create_user_recording(user, user, "My Recording", true, ["country"])
      #   last_response.status.should == 201
      #   recording = JSON.parse(last_response.body)

      #   # attempt to delete favorite as non-creator
      #   last_response = delete_favorite(fan, user, recording["id"])
      #   last_response.status.should == 403
      # end

      ######################### FRIENDS ########################
      it "should allow user to send friend request" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # get incoming friend requests (for fan)
        last_response = get_friend_requests(fan, fan)
        last_response.status.should == 200
        friend_requests = JSON.parse(last_response.body)
        friend_requests.size.should == 1
        friend_requests[0]["user_id"].should == user.id
        friend_requests[0]["friend_id"].should == fan.id
        friend_requests[0]["message"].should == "Please accept my friend request"

        # get outgoing friend requests (for user)
        last_response = get_friend_requests(user, user)
        last_response.status.should == 200
        friend_requests = JSON.parse(last_response.body)
        friend_requests.size.should == 1
        friend_requests[0]["user_id"].should == user.id
        friend_requests[0]["friend_id"].should == fan.id
        friend_requests[0]["message"].should == "Please accept my friend request"

        # accept friend request
        last_response = update_friend_request(fan, fan, friend_request["id"], "accept")
        last_response.status.should == 200

        # get user's friends
        last_response = get_friends(user, user)
        last_response.status.should == 200
        friends = JSON.parse(last_response.body)
        friends.size.should == 1
        friends[0]["id"].should == fan.id
        friends[0]["first_name"].should == fan.first_name
        friends[0]["last_name"].should == fan.last_name
        friends[0]["city"].should == fan.city
        friends[0]["state"].should == fan.state
        friends[0]["country"].should == fan.country
        friends[0]["email"].should == fan.email
        friends[0]["online"].should == fan.online
        friends[0]["photo_url"].should == fan.photo_url

        # get fan's friends
        last_response = get_friends(fan, fan)
        last_response.status.should == 200
        friends = JSON.parse(last_response.body)
        friends.size.should == 1
        friends[0]["id"].should == user.id
        friends[0]["first_name"].should == user.first_name
        friends[0]["last_name"].should == user.last_name
        friends[0]["city"].should == user.city
        friends[0]["state"].should == user.state
        friends[0]["country"].should == user.country
        friends[0]["email"].should == user.email
        friends[0]["online"].should == user.online
        friends[0]["photo_url"].should == user.photo_url
      end

      it "should not allow user to send friend request for another user" do
        dummy_user = FactoryGirl.create(:user)
        last_response = create_friend_request(user, dummy_user, fan, "My Message")
        last_response.status.should == 403
      end

      it "should allow user to ignore friend request" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # ignore friend request
        last_response = update_friend_request(fan, fan, friend_request["id"], "ignore")
        last_response.status.should == 200
      end

      it "should allow user to block friend request" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # block friend request
        last_response = update_friend_request(fan, fan, friend_request["id"], "block")
        last_response.status.should == 200

        # create another friend request to same user after blocking
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # target user's friend requests should be empty
        last_response = get_friend_requests(fan, fan)
        friend_requests = JSON.parse(last_response.body)
        friend_requests.size.should == 0
      end

      it "should allow user to mark friend request as spam" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # mark friend request as spam
        last_response = update_friend_request(fan, fan, friend_request["id"], "spam")
        last_response.status.should == 200
      end

      it "should not allow user to respond to another user's friend request" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # accept friend request as another user
        another_user = FactoryGirl.create(:user)
        last_response = update_friend_request(another_user, fan, friend_request["id"], "accept")
        last_response.status.should == 403
      end

      it "should allow user to delete friend" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # accept friend request
        last_response = update_friend_request(fan, fan, friend_request["id"], "accept")
        last_response.status.should == 200

        # delete the friend
        last_response = delete_friend(user, user, fan)
        last_response.status.should == 204

        last_response = get_friends(user, user)
        last_response.status.should == 200
        friends = JSON.parse(last_response.body)
        friends.size.should == 0
      end

      it "should not allow user to delete another user's friend" do
        # create friend request
        last_response = create_friend_request(user, user, fan, "Please accept my friend request")
        last_response.status.should == 201
        friend_request = JSON.parse(last_response.body)

        # accept friend request
        last_response = update_friend_request(fan, fan, friend_request["id"], "accept")
        last_response.status.should == 200

        # attempt to delete as another user
        another_user = FactoryGirl.create(:user)
        last_response = delete_friend(another_user, user, fan)
        last_response.status.should == 403
      end

      ######################### BAND INVITATIONS ########################
      it "should allow user to accept band invitation" do
        recipient = FactoryGirl.create(:user)

        # create invitation
        user.bands << band
        last_response = create_band_invitation(user, band.id, recipient.id)
        last_response.status.should == 201
        invitation = JSON.parse(last_response.body)

        # get invitation list for user
        last_response = get_band_invitations(recipient, recipient)
        last_response.status.should == 200
        invitation_list = JSON.parse(last_response.body)
        invitation_list.size.should == 1
        invitation_list[0]["id"].should == invitation["id"]

        # get invitation detail
        last_response = get_band_invitation(recipient, recipient, invitation["id"])
        last_response.status.should == 200
        invitation_details = JSON.parse(last_response.body)
        invitation_details["id"].should == invitation["id"]

        # accept invitation
        last_response = update_band_invitation(recipient, recipient, invitation["id"], true)
        last_response.status.should == 200

        last_response = get_band_details(recipient, band.id)
        last_response.status.should == 200
        band_details = JSON.parse(last_response.body)
        band_details["musicians"].size.should == 2

        last_response = get_band_invitation(recipient, recipient, invitation["id"])
        last_response.status.should == 200
        invitation_details = JSON.parse(last_response.body)
        invitation_details["accepted"].should == true

        # ensure user's band list is correct
        last_response = get_user_bands(recipient, recipient)
        last_response.status.should == 200
        band_list = JSON.parse(last_response.body)
        band_list.size.should == 1
        band_list[0]["id"].should == band.id

        # ensure user has recipient as friend
        last_response = get_friends(user, user)
        last_response.status.should == 200
        friends = JSON.parse(last_response.body)
        friends.size.should == 1
        friends[0]["id"].should == recipient.id
        friends[0]["first_name"].should == recipient.first_name
        friends[0]["last_name"].should == recipient.last_name
        friends[0]["city"].should == recipient.city
        friends[0]["state"].should == recipient.state
        friends[0]["country"].should == recipient.country
        friends[0]["email"].should == recipient.email
        friends[0]["online"].should == recipient.online
        friends[0]["photo_url"].should == recipient.photo_url

        # ensure recipient has user as friend
        last_response = get_friends(recipient, recipient)
        last_response.status.should == 200
        friends = JSON.parse(last_response.body)
        friends.size.should == 1
        friends[0]["id"].should == user.id
        friends[0]["first_name"].should == user.first_name
        friends[0]["last_name"].should == user.last_name
        friends[0]["city"].should == user.city
        friends[0]["state"].should == user.state
        friends[0]["country"].should == user.country
        friends[0]["email"].should == user.email
        friends[0]["online"].should == user.online
        friends[0]["photo_url"].should == user.photo_url
      end

      it "should allow user to decline band invitation" do
        recipient = FactoryGirl.create(:user)
        user.bands << band
        last_response = create_band_invitation(user, band.id, recipient.id)
        last_response.status.should == 201

        invitation = JSON.parse(last_response.body)
        last_response = update_band_invitation(recipient, recipient, invitation["id"], false)
      end
    end

    ########## UPDATE EMAIL ########
    describe "update email" do
      describe "begin update email" do
        it "success" do
          last_response = begin_update_email(user, "not_taken_test@jamkazam.com", user.password)
          last_response.status.should == 200
          UserMailer.deliveries.length.should == 1
        end

        it "bad args" do
          last_response = begin_update_email(user, "not_taken_test@jamkazam.com", 'wrong_password')
          last_response.status.should == 422
          UserMailer.deliveries.length.should == 0
        end

        it "no session" do
          last_response = begin_update_email(user, "not_taken_test@jamkazam.com", user.password, login=false)
          last_response.status.should == 403
          UserMailer.deliveries.length.should == 0
        end

        it "bad user" do
          login(user.email, user.password, 200, true)
          post "/api/users/someone_other_uuid/update_email.json",  { :update_email => "not_taken_test@jamkazam.com", :current_password => user.password}.to_json, "CONTENT_TYPE" => 'application/json'
          last_response.status.should == 403
          UserMailer.deliveries.length.should == 0
        end
      end

      describe "finalize update email" do
        it "success" do
          begin_update_email(user, "not_taken_test2@jamkazam.com", user.password)
          logout
          user.reload
          last_response = finalize_update_email(user.update_email_token)
          last_response.status.should == 200
          UserMailer.deliveries.length.should == 2 # one for begin, one for finalize
        end

        it "bad token" do
          last_response = finalize_update_email('junk')
          last_response.status.should == 404
          UserMailer.deliveries.length.should == 0
        end
      end
    end

    describe "get user" do
      it "should most data for self" do
        last_response, response = get_user(user)
        response["email"].should == user.email
      end

      describe "fetching other users" do
        let(:other_user) { FactoryGirl.create(:user) }
        let(:other_user_responses) { get_user(other_user, user) }
        let(:other_user_response) {other_user_responses[1]}

        describe "public permissions" do
          it { other_user_response["location"].should == other_user.location}
        end

        describe "hidden permissions" do
          it { other_user_response["email"].should be_nil }
        end
      end
    end

    describe "share_session" do

      let(:connection) { FactoryGirl.create(:connection, :user => user) }
      let(:instrument) { FactoryGirl.create(:instrument, :description => 'a great instrument') }
      let(:track) { FactoryGirl.create(:track, :connection => connection, :instrument => instrument) }
      let(:music_session) {
        ms = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true)
        # ms.connections << connection
        ms.save!
        connection.join_the_session(ms, true, nil, user, 10)
        ms
      }

      it "fetches facebook successfully" do
        login(user.email, user.password, 200, true)
        get "/api/users/#{user.id}/share/session/facebook.json?music_session=#{music_session.id}", nil, "CONTENT_TYPE" => 'application/json'

        last_response.status.should == 200
        response = JSON.parse(last_response.body)
        response['title'].include?("LIVE SESSION:").should be true
        response['description'].should == music_session.description
        response['photo_url'].include?('logo-256.png').should be true
        response['caption'].should == 'www.jamkazam.com'
      end
    end

    describe "notifications" do

      let(:other) { FactoryGirl.create(:user) }

      before(:each) do
        login(user.email, user.password, 200, true)
      end

      it "create text notification" do
        post "/api/users/#{user.id}/notifications.json", {message: 'bibbity bobbity boo', receiver:other.id }.to_json, "CONTENT_TYPE" => 'application/json'

        last_response.status.should == 201
        response = JSON.parse(last_response.body)
        response['id'].should_not be_nil

        # verify that it can be found
        get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE', receiver: other.id, limit:20, offset:0}, "CONTENT_TYPE" => 'application/json'
        last_response.status.should == 200
        response = JSON.parse(last_response.body)
        response.length.should == 1
      end

      it "bad language causes 422" do
        post "/api/users/#{user.id}/notifications.json", {message: 'ass', receiver:other.id }.to_json, "CONTENT_TYPE" => 'application/json'

        last_response.status.should == 422
        response = JSON.parse(last_response.body)
        response['errors']['message'].should == ['cannot contain profanity']
      end

      it "bad receiver causes 422" do
        post "/api/users/#{user.id}/notifications.json", {message: 'ass' }.to_json, "CONTENT_TYPE" => 'application/json'

        last_response.status.should == 422
        response = JSON.parse(last_response.body)
        response['errors']['target_user'].should == ['can\'t be blank']
      end

      describe "index" do
        describe "text message index" do
          it "requires receiver id" do
            # verify that it can be found
            get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE'}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            response['errors']['receiver'].should == ['can\'t be blank']
            last_response.status.should == 422
          end

          it "requires limit" do
            # verify that it can be found
            get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE', receiver: other.id, offset:0}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            response['errors']['limit'].should == ['can\'t be blank']
            last_response.status.should == 422
          end

          it "requires offset" do
            # verify that it can be found
            get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE',  receiver: other.id, limit:20}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            response['errors']['offset'].should == ['can\'t be blank']
            last_response.status.should == 422
          end

          it "returns no results" do
              # verify that it can be found
              get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE',  receiver: other.id, offset:0, limit:20}, "CONTENT_TYPE" => 'application/json'
              response = JSON.parse(last_response.body)
              response.length.should == 0
              last_response.status.should == 200
          end

          it "returns one results" do
            msg1 = FactoryGirl.create(:notification_text_message, source_user: user, target_user: other)
            # verify that it can be found
            get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE',  receiver: other.id, offset:0, limit:20}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            response.length.should == 1
            response[0]['notification_id'].should == msg1.id
            response[0]['description'].should == msg1.description
            response[0]['message'].should == msg1.message
            response[0]['source_user_id'].should == msg1.source_user_id
            response[0]['target_user_id'].should == msg1.target_user_id
            last_response.status.should == 200
            login(other.email, other.password, 200, true)
            get "/api/users/#{other.id}/notifications.json", {type: 'TEXT_MESSAGE',  receiver: user.id, offset:0, limit:20}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            response.length.should == 1
            response[0]['notification_id'].should == msg1.id
            response[0]['description'].should == msg1.description
            response[0]['message'].should == msg1.message
            response[0]['source_user_id'].should == msg1.source_user_id
            response[0]['target_user_id'].should == msg1.target_user_id
            last_response.status.should == 200
          end

          it "returns sorted results" do
            msg1 = FactoryGirl.create(:notification_text_message, source_user: user, target_user: other)
            msg2 = FactoryGirl.create(:notification_text_message, source_user: user, target_user: other, created_at: 1.days.ago)
            # verify that it can be found
            get "/api/users/#{user.id}/notifications.json", {type: 'TEXT_MESSAGE',  receiver: other.id, offset:0, limit:20}, "CONTENT_TYPE" => 'application/json'
            response = JSON.parse(last_response.body)
            last_response.status.should == 200
            response.length.should == 2
            response[0]['notification_id'].should == msg1.id
            response[1]['notification_id'].should == msg2.id
          end
        end
      end
    end


    describe "share_recording" do

      before(:each) do
          @connection = FactoryGirl.create(:connection, :user => user)
          @instrument = FactoryGirl.create(:instrument, :description => 'a great instrument')
          @track = FactoryGirl.create(:track, :connection => @connection, :instrument => @instrument)
          @music_session = FactoryGirl.create(:active_music_session, :creator => user, :musician_access => true)
          # @music_session.connections << @connection
          @music_session.save
          @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)
          @recording.reload
          @claimed_recording = @recording.claimed_recordings.first
        end

      it "fetches facebook successfully" do
        login(user.email, user.password, 200, true)
        get "/api/users/#{user.id}/share/recording/facebook.json?claimed_recording=#{@claimed_recording.id}", nil, "CONTENT_TYPE" => 'application/json'

        last_response.status.should == 200
        response = JSON.parse(last_response.body)
        response['title'].include?("RECORDING:").should be true
        response['description'].should == @claimed_recording.name
        response['photo_url'].include?('logo-256.png').should be true
        response['caption'].should == 'www.jamkazam.com'
      end
    end
  end
end
