<?php

use Drupal\DrupalExtension\Context\RawDrupalContext;
use Behat\Behat\Hook\Scope\BeforeScenarioScope;
use Behat\Behat\Hook\Scope\AfterScenarioScope;
use Behat\Testwork\Hook\Scope\BeforeSuiteScope;
use Behat\Testwork\Hook\Scope\AfterSuiteScope;

/**
 * Defines application features from the specific context.
 */
class FeatureContext extends RawDrupalContext {

  /**
   * The limit for the wait timeouts for javascript animations in ms.
   *
   * @var integer
   */
  protected $javascriptAnimationsTimeout = 5000;

  /**
   * The limit for the flagging using the document generator flag.
   *
   * @var integer
   */
  protected $documentGeneratorLimit;

  /**
   * Holds the state of the page loader before any test gets executed..
   *
   * @var bool
   */
  protected $pageLoaderState;

  /**
   * @BeforeSuite
   */
  public static function prepare(BeforeSuiteScope $scope) {
    // Disable the page loader before running the tests.
    \Drupal::state()->set(
      'svv_theme_use_pageloader',
      FALSE
    );
  }

  /**
   * @AfterSuite
   */
  public static function teardown(AfterSuiteScope $scope) {
    // Enable the page loader after running the tests.
    \Drupal::state()->set(
      'svv_theme_use_pageloader',
      TRUE
    );
  }

  /**
   * @When I hover the element :arg1
   */
  public function iHoverTheElement($arg1) {
    $element = $this->assertSession()->elementExists('css', $arg1);
    // Hover the element.
    $element->mouseOver();
  }

  /**
   * @When I close the popup
   */
  public function iCloseThePopup() {
    if (!!\Drupal::config('popup_dialog.settings')->get('popup_enabled')) {
      // Checks whether the popup is showing up.
      $popup = $this->assertSession()->elementExists('css', '.close-control');
      // Close the popup.
      $popup->click();
      // Wait for the popup fade out.
      $this->getSession()->wait(500);
    }
  }

  /**
   * @When I close the empty tooltip
   */
  public function iCloseTheEmptyTooltip() {
    // The document generator block in the sidebar.
    $document_generator_link = $this
      ->assertSession()
      ->elementExists('css', '.block-document-generator-counter .doc-gen-btn-container');

    $document_generator_link->mouseOver();
    $this->getSession()->wait(1000);

    // Check whether the tooltip actually appeared.
    $this
      ->assertSession()
      ->elementExists('css', '.tooltip-inner');

    // Close the tooltip by hovering over another element in the navbar.
    $search_link = $this
      ->assertSession()
      ->elementExists('css', '.search-api-form');
    $search_link->mouseOver();
    $this->getSession()->wait(500);

    $this
      ->assertSession()
      ->elementNotExists('css', '.tooltip-inner');
  }

  /**
   * @When I see :number nodes in the document generator counter block
   */
  public function iSeeNodesInTheDocumentGeneratorCounterBlock($number) {
    // Could be a good solution test if the element exist
    // multiple time after n milliseconds.
    $max_try = 0;
    while ($this->getSession()->getPage()->find('css','.doc-gen-counter-amount')->getText() != $number && $max_try < 40) {
      // Wait until it change on the page.
      $this->getSession()->wait(200);
      $max_try++;
    }

    if ($this->getSession()->getPage()->find('css','.doc-gen-counter-amount')->getText() != $number) {
      throw new \InvalidArgumentException(sprintf('Wrong value in the document generator counter block.'));
    }
  }

  /**
   * @Given I wait for the overview tooltip to appear
   */
  public function iWaitForTheOverviewTooltipToAppear() {
    // Wait for javascriptAnimationsTimeout seconds or till the the tooltip is visible.
    $this->getSession()->wait($this->javascriptAnimationsTimeout, 'jQuery(".tooltip-inner:visible").length > 0');
    // We assume the tooltip appeared.
    $this->assertSession()->elementExists('css', '.tooltip-inner');
  }

  /**
   * @Given I wait for the overview tooltip to disappear
   */
  public function iWaitForTheOverviewTooltipToDisappear() {
    $this->getSession()->wait($this->javascriptAnimationsTimeout);
    // Wait till it disappears again or till javascriptAnimationsTimeout seconds go by.
    $this->getSession()->wait($this->javascriptAnimationsTimeout, 'jQuery(".tooltip-inner:visible").length === 0');
    // At this point it should have disappeared again.
    $this->assertSession()->elementNotExists('css', '.tooltip-inner');    
  }  

  /**
   * @Then I activate the document generator flag links
   */
  public function iActivateTheDocGenFlagLinks() {
    // The document generator toggle button on the bottom right of overview
    // pages.
    /** @var \Behat\Mink\Element\NodeElement $document_generator_toggle_button */
    $document_generator_toggle_button = $this
      ->assertSession()
      ->elementExists('css', '.doc-gen-toggle-btn');
    $document_generator_toggle_button->click();
  }

  /**
   * @Then I should not see the document generator flag link
   */
  public function iShouldNotSeeTheDocumentGeneratorFlagLink() {
    // The document flag/unflag in the node teasers.
    $document_generator_flag = $this
      ->assertSession()
      ->elementExists('css', '.js-document-generator a');

    if ($document_generator_flag->isVisible()) {
      throw new \LogicException(sprintf('Document generator flags on teasers are visible'));
    }
  }

  /**
   * @Then I should see the document generator flag link
   */
  public function iShouldSeeTheDocumentGeneratorFlagLink() {
    // The document flag/unflag in the node teasers.
    $document_generator_flag = $this
      ->assertSession()
      ->elementExists('css', '.js-document-generator a');

    if (!$document_generator_flag->isVisible()) {
      throw new \LogicException(sprintf('Document generator flags on teasers are not visible'));
    }
  }

  /**
   * @BeforeScenario @documentGeneratorLimit
   */
  public function beforeDocumentGeneratorLimitScenario(BeforeScenarioScope $scope) {
    // Save the current value of the limit.
    $this->documentGeneratorLimit = \Drupal::config('svv_backend.settings')->get('document_generator_flag_limit');
    // Set the limit of the document generator to 3 nodes.
    \Drupal::configFactory()->getEditable('svv_backend.settings')->set('document_generator_flag_limit', 3)->save();
  }

  /**
   * @AfterScenario @documentGeneratorLimit
   */
  public function afterDocumentGeneratorLimitScenario(AfterScenarioScope $scope) {
    // Restore the original flag limit.
    \Drupal::configFactory()->getEditable('svv_backend.settings')->set('document_generator_flag_limit', $this->documentGeneratorLimit)->save();
  }

  /**
   * I wait for the navbar tooltip to appear
   * 
   * @Given I wait for the navbar tooltip to appear
   */
  public function iWaitForTheNavbarTooltipToAppear() {
    // Wait for javascriptAnimationsTimeout seconds or till the the navbar tooltip is visible.
    $this->getSession()->wait($this->javascriptAnimationsTimeout, 'jQuery(".tooltip-navbar:visible").length > 0');
    // We assume the navbar tooltip appeared.
    $this->assertSession()->elementExists('css', '.tooltip-navbar');
  }
  
  /**
   * I wait for the navbar tooltip to disappear
   * 
   * @Given I wait for the navbar tooltip to disappear
   */
  public function iWaitForTheNavbarTooltipToDisappear() {
    $this->getSession()->wait($this->javascriptAnimationsTimeout);
    // Wait for javascriptAnimationsTimeout seconds or till the the navbar tooltip is visible.
    $this->getSession()->wait($this->javascriptAnimationsTimeout, 'jQuery(".tooltip-navbar:visible").length === 0');
    // We assume the navbar tooltip disappeared.
    $this->assertSession()->elementNotExists('css', '.tooltip-navbar');
  }

}
