# frozen_string_literal: true

#
# Copyright (C) 2015 - present Instructure, Inc.
#
# This file is part of Canvas.
#
# Canvas is free software: you can redistribute it and/or modify it under
# the terms of the GNU Affero General Public License as published by the Free
# Software Foundation, version 3 of the License.
#
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
# details.
#
# You should have received a copy of the GNU Affero General Public License along
# with this program. If not, see <http://www.gnu.org/licenses/>.

module LoginAndSessionMethods
  def create_session(pseudonym)
    if caller.grep(%r{onceler/recorder.*record!}).present?
      raise "don't double sessions in a `before(:once)` block; do it in a `before(:each)` so the stubbing works for all examples and not just the first one"
    end

    @session_stubbed = true
    allow_any_instance_of(PseudonymSession).to receive(:record).and_wrap_original do |original|
      next original.call unless @session_stubbed

      pseudonym.reload
    end
  end

  def destroy_session
    @session_stubbed = false
  end

  def user_session(user)
    create_session(pseudonym(user))
  end

  def user_logged_in(opts = {})
    user_with_pseudonym({ active_user: true }.merge(opts))
    create_session(@pseudonym)
  end

  def course_with_teacher_logged_in(opts = {})
    user_logged_in(opts)
    course_with_teacher({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def course_with_student_logged_in(opts = {})
    user_logged_in(opts)
    course_with_student({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def course_with_observer_logged_in(opts = {})
    user_logged_in(opts)
    course_with_observer({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def course_with_ta_logged_in(opts = {})
    user_logged_in(opts)
    course_with_ta({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def course_with_designer_logged_in(opts = {})
    user_logged_in(opts)
    course_with_designer({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def course_with_admin_logged_in(opts = {})
    account_admin_user({ active_user: true }.merge(opts))
    user_logged_in({ user: @user }.merge(opts))
    course_with_teacher({ user: @user, active_course: true, active_enrollment: true }.merge(opts))
  end

  def provision_quizzes_next(account)
    account.root_account.settings[:provision] = { "lti" => "lti url" }
    account.root_account.save!
  end

  def admin_logged_in(opts = {})
    account_admin_user({ active_user: true }.merge(opts))
    user_logged_in({ user: @user }.merge(opts))
  end

  def site_admin_logged_in(opts = {})
    site_admin_user({ active_user: true }.merge(opts))
    user_logged_in({ user: @user }.merge(opts))
  end

  def enter_student_view(opts = {})
    course = opts[:course] || @course || course(opts)
    get "/courses/#{course.id}/users"
    driver.execute_script("$('#easy_student_view').click()")
    wait_for_ajaximations
  end

  def leave_student_view
    expect_new_page_load { f(".leave_student_view").click }
  end

  def fill_in_login_form(username, password)
    user_element = f("#pseudonym_session_unique_id")
    user_element.send_keys(username)
    password_element = f("#pseudonym_session_password")
    password_element.send_keys(password)
    password_element.submit
    wait_for_ajaximations
  end

  # don't use this unless you are actually testing the login/logout
  # process; instead prefer create_session or the various *_logged_in
  # methods above
  def login_as(username = "nobody@example.com", password = "asdfasdf")
    if Onceler.recording
      raise "don't use real logins with once-ler, since a session cookie could be valid across specs if the pseudonym is shared"
    end

    get "/login"
    expect_new_page_load { fill_in_login_form(username, password) }
    expect_logout_link_present
  end

  def masquerade_as(user)
    masquerade_url = "/users/#{user.id}/masquerade"
    get masquerade_url
    f('a[href="' + masquerade_url + '"]').click
  end

  def displayed_username
    f("#global_nav_profile_link").click
    f('[aria-label="Profile tray"] h2').text
  end

  def expect_logout_link_present
    logout_element = begin
      f("#global_nav_profile_link").click
      wait_for_animations
      fj('form[action="/logout"] button:contains("Logout")')
    end
    expect(logout_element).to be_present
    logout_element
  end
end
