<?php

namespace Drupal\lingotek\Controller;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\lingotek\LanguageLocaleMapperInterface;
use Drupal\lingotek\LingotekInterface;
use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\lingotek\LingotekSetupTrait;
use Psr\Log\LoggerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
 * Base class for handling all Lingotek-related routes.
 */
abstract class LingotekControllerBase extends ControllerBase {

  use LingotekSetupTrait;

  /**
   * A Symfony request instance
   *
   * @var \Symfony\Component\HttpFoundation\Request
   */
  protected $request;

  /**
   * The config factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected $configFactory;

  /**
   * The language-locale mapper.
   *
   * @var \Drupal\lingotek\LanguageLocaleMapperInterface
   */
  protected $languageLocaleMapper;

  /**
   * The form builder.
   *
   * @var \Drupal\Core\Form\FormBuilderInterface
   */
  protected $formBuilder;

  /**
   * A logger instance.
   *
   * @var \Psr\Log\LoggerInterface
   */
  protected $logger;

  /**
   * Constructs a LingotekControllerBase object.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The Request instance.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\lingotek\LingotekInterface $lingotek
   *   The lingotek service.
   * @param \Drupal\lingotek\LanguageLocaleMapperInterface $language_locale_mapper
   *   The language-locale mapper.
   * @param \Drupal\Core\Form\FormBuilderInterface $form_builder
   *   The form builder.
   * @param \Psr\Log\LoggerInterface $logger
   *   A logger instance.
   */
  public function __construct(Request $request, ConfigFactoryInterface $config_factory, LingotekInterface $lingotek, LanguageLocaleMapperInterface $language_locale_mapper, FormBuilderInterface $form_builder, LoggerInterface $logger) {
    $this->request = $request;
    $this->configFactory = $config_factory;
    $this->lingotek = $lingotek;
    $this->languageLocaleMapper = $language_locale_mapper;
    $this->formBuilder = $form_builder;
    $this->logger = $logger;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('request_stack')->getCurrentRequest(),
      $container->get('config.factory'),
      $container->get('lingotek'),
      $container->get('lingotek.language_locale_mapper'),
      $container->get('form_builder'),
      $container->get('logger.channel.lingotek')
    );
  }

  /**
   * Checks if site is connected to Lingotek.
   *
   * @return boolean TRUE if connected, FALSE otherwise.
   */
  public function connected() {
    $access_token = $this->request->query->get('access_token');
    if ($access_token) {
      $config = \Drupal::configFactory()->getEditable('lingotek.settings');
      $config->set('access_token', $access_token);
      $config->save();
      return TRUE;
    }
    return FALSE;
  }

  /**
   * Generates and pushes Basic Auth credentials for the project callback.
   *
   * @param string $project_id
   *   The Lingotek project ID.
   * @param string $callback_url
   *   The callback URL.
   *
   * @return bool
   *   TRUE if pushing succeeded, FALSE otherwise.
   *
   * @throws \Drupal\lingotek\Exception\LingotekApiException
   */
  protected function pushProjectCallbackCredentials($project_id, $callback_url) {
    $site_uuid = $this->configFactory->get('system.site')->get('uuid');
    if (empty($site_uuid)) {
      $site_uuid = \Drupal::service('uuid')->generate();
    }
    $username = 'drupal-' . $site_uuid;
    $password = base64_encode(random_bytes(32));

    if (!$this->lingotek->setProjectCallbackAuth($project_id, $callback_url, $username, $password)) {
      return FALSE;
    }
    $this->configFactory->getEditable('lingotek.account')
      ->set('callback_url', $callback_url)
      ->set('notify_auth_username', $username)
      ->set('notify_auth_password_hash', password_hash($password, PASSWORD_BCRYPT))
      ->save();

    return TRUE;
  }

}
