require 'browser'

module PandaPal::Helpers::ControllerHelper
  def save_session
    current_session.try(:save)
  end

  def current_session
    @current_session ||= PandaPal::Session.find_by(session_key: session_key) if session_key
    @current_session ||= PandaPal::Session.new(panda_pal_organization_id: current_organization.id)
  end

  def current_organization
    @organization ||= PandaPal::Organization.find_by!(key: organization_key) if organization_key
    @organization ||= PandaPal::Organization.find_by(id: organization_id) if organization_id
    @organization ||= PandaPal::Organization.find_by_name(Apartment::Tenant.current)
  end

  def current_session_data
    current_session.data
  end

  def session_changed?
    current_session.changed? && current_session.changes[:data].present?
  end

  def validate_launch!
    authorized = false
    if @organization = params['oauth_consumer_key'] && PandaPal::Organization.find_by_key(params['oauth_consumer_key'])
      authenticator = IMS::LTI::Services::MessageAuthenticator.new(request.original_url, request.request_parameters, @organization.secret)
      authorized = authenticator.valid_signature?
    end
    render plain: 'Invalid Credentials, please contact your Administrator.', :status => :unauthorized unless authorized
    authorized
  end

  def switch_tenant(organization = current_organization, &block)
    return unless organization
    raise 'This method should be called in an around_action callback' unless block_given?

    Apartment::Tenant.switch(organization.name) do
      yield
    end
  end

  # Browsers that prevent 3rd party cookies by default (Safari and IE) run into problems
  # with CSRF handling because the Rails session cookie isn't set. To fix this, we
  # redirect the current page to the LTI using JavaScript, which will set the cookie,
  # and then immediately redirect back to Canvas.
  def fix_iframe_cookies
    if params[:safari_cookie_fix].present?
      session[:safari_cookie_fixed] = true
      redirect_to params[:return_to]
    else
      render 'panda_pal/lti/iframe_cookie_fix', layout: false
    end
  end

  def cookies_need_iframe_fix?
    browser.safari? && !request.referrer.include?('sessionless_launch') && !session[:safari_cookie_fixed]
  end

  def forbid_access_if_lacking_session
    if cookies_need_iframe_fix?
      fix_iframe_cookies
    else
      render plain: 'You should do an LTI Tool Launch.', status: :unauthorized unless valid_session?
    end
  end

  def valid_session?
    [
      current_session.persisted?,
      current_organization,
      current_session.panda_pal_organization_id == current_organization.id,
      Apartment::Tenant.current == current_organization.name
    ].all?
  end

  private
  def organization_key
    params[:oauth_consumer_key] || session[:organization_key]
  end

  def organization_id
    params[:organization_id]
  end

  def session_key
    params[:session_key] || session_key_header || flash[:session_key] || session[:session_key]
  end

  def session_key_header
    if match = request.headers['Authorization'].try(:match, /token=(.+)/)
      match[1]
    end
  end
end