# -*- coding: utf-8 -*-

require 'builder'

class Slide
  attr_accessor :img_url, :header, :vid_url

  def initialize(header, img_url, vid_url)
    @img_url = img_url # preview image
    @header = header
    @vid_url = vid_url + '?autoplay=1'
  end
end

class UsersController < ApplicationController

  include ClientHelper

  before_filter :signed_in_user,
                only: [:index, :edit, :update, :destroy]
  before_filter :correct_user,   only: [:edit, :update]
  before_filter :admin_user,     only: :destroy
  before_filter :is_native_client
  before_filter :ip_blacklist, :only => [:create]


  rescue_from 'JamRuby::PermissionError' do |exception|
    @exception = exception
    render :file => 'public/403.html', :status => 403, :layout => false
  end
  
  def index
    @users = User.paginate(page: params[:page])
  end

  def show
    @user = User.find(params[:id])
  end

  def new
    @no_user_dropdown = true

    @invited_user = load_invited_user(params)

    @plan_code = params[:plan_code] || ''

    if @invited_user && @invited_user.email
      user = User.find_by_email(@invited_user.email)
      if user && (!current_user || current_user.id != user.id)
        sign_in(user)
        friend_request = FriendRequest.find_by_user_id_and_friend_id(@invited_user.sender_id, user.id)
        if !friend_request
          redirect_url = "/client#/home"
        else
          redirect_url = "/client#/home/accept-friend-request/d1=#{friend_request.id}"
        end
        redirect_to redirect_url
        return
      end
    end

    if current_user
      if params["redirect-to"]
        redirect_to params["redirect-to"]
      else
        redirect_to client_url
      end
      return
    end

    @fb_signup = load_facebook_signup(params)


    # check if the email specified by @fb_signup already exists in the databse--if so, log them in and redirect
    if @fb_signup && @fb_signup.email
      user = User.find_by_email_and_email_confirmed(@fb_signup, true)
      if user
        # update user_authorization for user because this is fresher
        user.update_fb_authorization(@fb_signup)
        sign_in(user)
        redirect_to client_url
        return
      end
    end

    # check if the uid specified by @fb_signup already exists in the databse--if so, log them in and redirect
    if @fb_signup && @fb_signup.uid
      user_authorization = UserAuthorization.find_by_uid_and_provider(@fb_signup.uid, 'facebook')
      # update user_authorization for user because this is fresher
      if user_authorization
        user_authorization.user.update_fb_authorization(@fb_signup)
        sign_in(user_authorization.user)
        redirect_to client_url
        return
      end
    end

    @affiliate_partner = load_affiliate_partner(params)

    @signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner)

    load_location(request.remote_ip)

    @user = User.new
    @user.musician = true # default the UI to musician as selected option

    # preseed the form with the invited email as a convenience to the user
    @user.email = @invited_user.email unless @invited_user.nil?

    if @fb_signup
      @user.email = @fb_signup.email
      @user.first_name = @fb_signup.first_name
      @user.last_name = @fb_signup.last_name
      @user.gender = @fb_signup.gender
    end

    render :layout => 'web'
  end

  def create

    if current_user
      redirect_to client_url
      return
    end

    signup_hint = SignupHint.where(anonymous_user_id: anonymous_user.id).where('expires_at > ?', Time.now).first if anonymous_user

    @fb_signup = load_facebook_signup(params)

    # check if the email specified by @fb_signup already exists in the database--if so, log them in and redirect
    if @fb_signup && @fb_signup.email
      user = User.find_by_email_and_email_confirmed(@fb_signup, true)
      if user
        # update user_authorization for user because this is fresher
        user.update_fb_authorization(@fb_signup)
        sign_in(user)
        redirect_url = handle_signup_hint(user, signup_hint, client_url)
        redirect_to redirect_url
        return
      end
    end

    # check if the uid specified by @fb_signup already exists in the database--if so, log them in and redirect
    if @fb_signup && @fb_signup.uid
      user_authorization = UserAuthorization.find_by_uid_and_provider(@fb_signup.uid, 'facebook')
      # update user_authorization for user because this is fresher
      if user_authorization
        user_authorization.user.update_fb_authorization(@fb_signup)
        sign_in(user_authorization.user)

        redirect_url = handle_signup_hint(user_authorization.user, signup_hint, client_url)
        redirect_to redirect_url
        return
      end
    end

    @invited_user = load_invited_user(params)
    @affiliate_partner = load_affiliate_partner(params)
    @signup_postback = load_postback(@invited_user, @fb_signup, @affiliate_partner)

    
    instruments = fixup_instruments(params[:jam_ruby_user][:instruments])

    birth_date = fixup_birthday(params[:jam_ruby_user]["birth_date(2i)"], params[:jam_ruby_user]["birth_date(3i)"], params[:jam_ruby_user]["birth_date(1i)"])
    location = { :country =>  params[:jam_ruby_user][:country], :state =>  params[:jam_ruby_user][:state], :city =>  params[:jam_ruby_user][:city]}
    desired_plan_code = params[:jam_ruby_user][:desired_plan_code]
    if desired_plan_code ==''
      desired_plan_code = nil
    end

    terms_of_service = params[:jam_ruby_user][:terms_of_service].nil? || params[:jam_ruby_user][:terms_of_service] == "0"? false : true
    musician = params[:jam_ruby_user][:musician]

    @user = UserManager.new.signup(remote_ip: request.remote_ip,
                                   first_name: params[:jam_ruby_user][:first_name],
                                   last_name: params[:jam_ruby_user][:last_name],
                                   email: params[:jam_ruby_user][:email],
                                   password: params[:jam_ruby_user][:password],
                                   password_confirmation: params[:jam_ruby_user][:password_confirmation],
                                   terms_of_service: terms_of_service,
                                   instruments: instruments,
                                   birth_date: birth_date,
                                   location: location,
                                   musician: musician,
                                   recaptcha_response: params['g-recaptcha-response'],
                                   invited_user: @invited_user,
                                   fb_signup: @fb_signup,
                                   signup_confirm_url: ApplicationHelper.base_uri(request) + "/confirm",
                                   affiliate_referral_id: cookies[:affiliate_visitor],
                                   affiliate_partner: @affiliate_partner,
                                   timezone: current_timezone,
                                   origin: origin_cookie,
                                   desired_plan_code: desired_plan_code )
        
    # check for errors
    if @user.errors.any?
      # render any @user.errors on error
      load_location(request.remote_ip, location)
      gon.signup_errors = true
      gon.musician_instruments = instruments
      gon.plan_code = desired_plan_code
      render "new", :layout => 'web'
    else
      sign_in @user

      new_user(@user, signup_hint) # sets a cookie used for GA analytics (one-time new user stuff in JavaScript)
      destination = @user.musician ? :congratulations_musician : :congratulations_fan
      redirect_url = handle_signup_hint(@user, signup_hint, {:action => destination, friend: @invited_user.nil? ? nil : @invited_user.sender.name})
      redirect_to redirect_url
    end
  end

  def congratulations_fan
    @no_user_dropdown = true
    render :layout => "web"
  end

  def congratulations_musician
    @no_user_dropdown = true
    render :layout => "web"
  end

  def downloads
    @no_user_dropdown = true
    @page_context = 'standalone'
    render :layout => "web"
  end

  # DO NOT USE CURRENT_USER IN THIS ROUTINE UNLESS REDIRECTING. IT'S CACHED FOR THE WHOLE SITE
  def home

    if current_user
      redirect_to "/client#/home"
      return
    end

    gon.news = News.all

    render :layout => "modern"
  end

  def signup_confirm
    signup_token = params[:signup_token]

    @user = UserManager.new.signup_confirm(signup_token, request.remote_ip)

    if !@user.nil? && !@user.errors.any?
      #UserMailer.welcome_message(@user).deliver_now
    elsif !@user.nil?
      # new user with validation errors;
      logger.debug("#{@user} has errors. can not sign in until remedied.  #{@user.errors.inspect}")
    end
    # let page have signup_token in javascript
    gon.signup_token = signup_token

    # let errors fall through to signup_confirm.html.erb
    render :layout => 'web'
  end

  def edit
  end

  def update
    if @user.update_attributes(params[:jam_ruby_user])
      flash[:success] = "Profile updated"
      sign_in @user
      redirect_to @user
    else
      render 'edit'
    end
  end

  def destroy
    User.find(params[:id]).destroy
    flash[:success] = "User destroyed."
    redirect_to users_url
  end

  def request_reset_password
    render 'request_reset_password', :layout => 'landing'
  end
  
  def reset_password
    begin
      @reset_password_email = params[:jam_ruby_user][:email]

      if @reset_password_email.blank?
        @reset_password_error = "Please enter an email address"
        render 'request_reset_password', :layout => 'landing'
        return
      end

      @reset_password_email.strip!

      unless User::VALID_EMAIL_REGEX.match(@reset_password_email)
        @reset_password_error = "Please enter a valid email address"
        render 'request_reset_password', :layout => 'landing'
        return
      end

      @user = User.reset_password(@reset_password_email, ApplicationHelper.base_uri(request))
      render 'sent_reset_password', :layout => 'landing'
    rescue JamRuby::JamArgumentError
      # Dont tell the user if this error occurred to prevent scraping email addresses.
      render 'sent_reset_password', :layout => 'landing'
    end
  end
  
  def reset_password_token
    render 'reset_password_token', :layout => 'landing'
  end

  def reset_password_token_post
    begin
      User.set_password_from_token(params[:jam_ruby_user][:email], params[:jam_ruby_user][:token], params[:jam_ruby_user][:password], params[:jam_ruby_user][:password_confirmation])
      redirect_to reset_password_complete_path({email: params[:jam_ruby_user][:email]})
    rescue JamRuby::JamArgumentError => e
      @password_error = e.field_message
      params[:email] = params[:jam_ruby_user][:email]
      params[:token] = params[:jam_ruby_user][:token]
      render 'reset_password_token', :layout => 'landing'
    end
  end

  def reset_password_complete
    render 'reset_password_complete', :layout => 'landing'
  end

  def finalize_update_email
    # this corresponds to when the user clink a link in their new email address to configure they want to use it,
    # and verify their new address is real
    token = params[:token]

    gon.ensure = true
    gon.update_email_token = token

    render :layout => 'landing'
  end

  def jnlp
    headers["Content-Type"] = "application/x-java-jnlp-file"
    headers["Cache-Control"] = "public"
    headers["Content-Disposition"] = "attachment;filename='ping#{params[:isp]}.jnlp'"
    jnlp = ''
    xml = Builder::XmlMarkup.new(:indent => 2, :target => jnlp)
    xml.instruct!
    jnlpurl = isp_ping_url(:isp => params[:isp], 
                           :format => :jnlp, 
                           :host => 'www.jamkazam.com', 
                           :port => '80')
    xml.jnlp(:spec => '1.0+', 
             :href => jnlpurl, 
             :codebase => "http://www.jamkazam.com/isp") do
      xml.information do
        xml.title 'Ping'
        xml.vendor 'JamKazam'
      end
      xml.resources do
        xml.j2se(:version => "1.6+", :href => "http://java.sun.com/products/autodl/j2se")
        xml.jar(:href => 'http://www.jamkazam.com/isp/ping.jar', :main => 'true')
      end
      xml.tag!('application-desc', 
               :name => "Ping", 
               'main-class' => "com.jamkazam.ping.Ping", 
               :width => "400", 
               :height => "600") do
        xml.comment!('usage: Ping [label=]addr[:port] ... [-c <count>] [-s <size>] -u <url> -i <isp> [-a]')
        xml.argument('foo=etch.dyndns.org:4442') 
        xml.argument('bar=etch.dyndns.org:4442') 
        xml.argument("-uhttp://www.jamkazam.com#{isp_scoring_path}") 
        xml.argument("-i#{params[:isp]}") 
        xml.argument('-a') 
      end
      xml.update(:check => 'background')
    end
    send_data jnlp, :type=>"application/x-java-jnlp-file" 
  end

  def isp
    @isps = {
      'tw' => ['Time Warner', 'tw.jpg'],
      'vz' => ['Verizon', 'vz.png'],
      'att' => ['AT&T', 'att.png'],
      'cc' => ['Comcast', 'cc.png'],
      'other' => ['Other', 'other.jpg']
    }
    render :layout => "landing"
  end

  def endorse
    if uu = current_user || 
        uu = User.where(['id = ? AND first_social_promoted_at IS NULL',params[:id]]).limit(1).first
      uu.first_social_promoted_at = Time.now
      uu.save!
    end if params[:id].present? && (service=params[:service]).present?

    service ||= 'facebook'
    url = CGI::escape('https://www.jamkazam.com')
    txt = CGI::escape('Check out JamKazam -- Play music together over the Internet as if in the same room')
    if 'twitter'==service
      url = "https://twitter.com/intent/tweet?text=#{txt}&url=#{url}"
    elsif 'facebook'==service
      url = "https://www.facebook.com/sharer/sharer.php?u=#{url}&t=#{txt}"
    elsif 'google'==service
      url = "https://plus.google.com/share?url=#{url}"
    end
    if 'email'==params[:src]
      js =<<JS
<script type="text/javascript">
$(function() {
  // // removed because we are juggling 20 events max in GA
  // JK.GA.trackJKSocial(JK.GA.Categories.jkLike, '#{service}', 'email');
  window.location = "#{url}";
});
</script>
JS
      render :inline => js, :layout => 'landing'
    else
      redirect_to url 
    end
  end

  def unsubscribe
    unless @user = User.read_access_token(params[:user_token])
      redirect_to '/'
    end if params[:user_token].present?

    #if request.get?

    #elsif request.post?
      @user.subscribe_email = false
      @user.save!
    #end

    render text: 'You have been unsubscribed.'
  end

  private

  def is_native_client
    @nativeClient = is_native_client?
  end

  def correct_user
    @user = User.find(params[:id])
    redirect_to(root_url) unless current_user?(@user)
  end

  # the User Model expects instruments in a different format than the form submits it
  # so we have to fix it up.
  def fixup_instruments(original_instruments)
    # if an instrument is selected by the user in the form, it'll show up in this array
    instruments = []

    # ok, sweep through all the fields submitted, looking for selected instruments.
    # also, make up priority because we don't ask for it (but users can fix it later on their profile)
    priority = 0
    unless original_instruments == nil
      original_instruments.each do |key, value|
        if !value["selected"].nil?
          instruments << { :instrument_id => key, :proficiency_level => value["proficiency"].to_i, :priority => priority }
          priority = priority + 1
        end
      end
    end
    if instruments.length == 0
      # default to guitar when non-specified
      instruments << {:instrument_id => "acoustic guitar", :proficiency_level => 3, :priority => 1}
    end

    return instruments
  end

  # the User Model expects instruments in a different format than the form submits it
  # so we have to fix it up.
  def fixup_birthday(month, day, year)
    if month.blank? || day.blank? || year.blank?
      # invalid birthdate, so return nil
      return nil
    end

    return Date.new(year.to_i, month.to_i, day.to_i)
  end

  def load_facebook_signup(params)
    lookup_id = params[:facebook_signup]

    FacebookSignup.find_by_lookup_id(lookup_id)
  end

  def load_invited_user(params)
    # check if this an anonymous request, or result of invitation code
    invitation_code = params[:invitation_code]

    invited_user = nil
    unless invitation_code.nil?
      # we only want to find invitations that have not been accepted
      invited_user = InvitedUser.find_by_invitation_code(invitation_code)
    end
    return invited_user
  end

  def load_affiliate_partner(params)
    partner_id = params[:affiliate_partner_id]

    AffiliatePartner.find(partner_id) if partner_id
  end

  def load_location(remote_ip, location = nil)
    # useful if you need to repro something on 127.0.0.1
    # remote_ip = ' 23.119.29.89'

    @location = location

    if @location.nil?
      @location = GeoIpLocations.lookup(remote_ip)
    end

    @location[:country] = "US" if @location[:country].nil?

    @countriesx = MaxMindManager.countries
    # populate regions based on current country
    @regions = MaxMindManager.regions(@location[:country])
    @cities = @location[:state].nil? ? [] : MaxMindManager.cities(@location[:country], @location[:state])
  end

  def load_postback(invited_user, fb_signup, affiliate_partner)
    query = {}
    query[:invitation_code] = invited_user.invitation_code if invited_user
    query[:facebook_signup] = fb_signup.lookup_id if fb_signup
    query[:affiliate_partner_id] = affiliate_partner.id if affiliate_partner
    if query.length > 0
      signup_path + "?" + query.to_query
    else
      signup_path
    end
  end  
end
