<?php

namespace Drupal\straker_translate\Controller;

use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityInterface;
use Drupal\Core\Entity\EntityTypeBundleInfoInterface;
use Drupal\Core\Form\FormBuilderInterface;
use Drupal\straker_translate\Exception\StrakerTranslateApiException;
use Drupal\straker_translate\Exception\StrakerTranslateContentEntityStorageException;
use Drupal\straker_translate\Exception\StrakerTranslateDocumentArchivedException;
use Drupal\straker_translate\Exception\StrakerTranslateDocumentLockedException;
use Drupal\straker_translate\Exception\StrakerTranslateDocumentAlreadyCompletedException;
use Drupal\straker_translate\Exception\StrakerTranslateDocumentAlreadyUploaded;
use Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException;
use Drupal\straker_translate\Exception\StrakerTranslatePaymentRequiredException;
use Drupal\straker_translate\LanguageLocaleMapperInterface;
use Drupal\straker_translate\StrakerTranslate;
use Drupal\Core\Url;
use Drupal\straker_translate\Exception\StrakerTranslateProcessedWordsLimitException;
use Drupal\straker_translate\StrakerTranslateConfigurationServiceInterface;
use Drupal\straker_translate\StrakerTranslateInterface;
use Psr\Log\LoggerInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;

/**
 *
 */
class StrakerTranslateEntityController extends StrakerTranslateControllerBase {

  protected $translations_link;

  /**
   * The Straker Translate configuration service.
   *
   * @var \Drupal\straker_translate\StrakerTranslateConfigurationServiceInterface
   */
  protected $straker_translateConfiguration;

  /**
   * The entity type bundle info.
   *
   * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface
   */
  protected $entityTypeBundleInfo;

  /**
   * Constructs a StrakerTranslateEntityController object.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The Request instance.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The factory for configuration objects.
   * @param \Drupal\straker_translate\StrakerTranslateInterface $straker_translate
   *   The straker_translate service.
   * @param \Drupal\straker_translate\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.
   * @param \Drupal\straker_translate\StrakerTranslateConfigurationServiceInterface $straker_translate_configuration
   *   The Straker Translate configuration service.
   * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info
   *   The entity type bundle info.
   */
  public function __construct(Request $request, ConfigFactoryInterface $config_factory, StrakerTranslateInterface $straker_translate, LanguageLocaleMapperInterface $language_locale_mapper, FormBuilderInterface $form_builder, LoggerInterface $logger, StrakerTranslateConfigurationServiceInterface $straker_translate_configuration, EntityTypeBundleInfoInterface $entity_type_bundle_info) {
    parent::__construct($request, $config_factory, $straker_translate, $language_locale_mapper, $form_builder, $logger);
    $this->straker_translateConfiguration = $straker_translate_configuration;
    $this->entityTypeBundleInfo = $entity_type_bundle_info;
  }

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

  /**
   *
   */
  public function checkUpload($doc_id) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');

    $entity = $translation_service->loadByDocumentId($doc_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot check upload for @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot check upload for @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    try {
      if ($translation_service->checkSourceStatus($entity)) {
        $this->messenger()->addStatus(t('The Document translations for @entity_type %title is complete.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
      else {
        $this->messenger()->addStatus(t('The Document translations for @entity_type %title is still in progress, try again after some time.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()->addError(t('Document @entity_type %title was not found. Please upload again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The check for @entity_type status failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }

    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function lockTarget($doc_id, $locale) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');
    /** @var \Drupal\straker_translate\LanguageLocaleMapperInterface $languageMapper */
    $languageMapper = \Drupal::service('straker_translate.language_locale_mapper');

    $entity = $translation_service->loadByDocumentId($doc_id);
    $drupal_language = $languageMapper->getConfigurableLanguageForLocale($locale);
    $langcode = $drupal_language->getId();
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot lock target for @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot lock target for @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    try {
      $translation_service->setTargetStatus($entity, $langcode, StrakerTranslate::STATUS_LOCKED);
      $this->messenger()->addStatus(t('The @locale translation for @entity_type %title is locked.', ['@locale' => $locale, '@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()->addError(t('Document @entity_type %title was not found.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The target lock for @entity_type failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }

    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function unlockTarget($doc_id, $locale) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');
    /** @var \Drupal\straker_translate\LanguageLocaleMapperInterface $languageMapper */
    $languageMapper = \Drupal::service('straker_translate.language_locale_mapper');

    $entity = $translation_service->loadByDocumentId($doc_id);
    $drupal_language = $languageMapper->getConfigurableLanguageForLocale($locale);
    $langcode = $drupal_language->getId();
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot unlock target for @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot unlock target for @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    try {
      $translation_service->setTargetStatus($entity, $langcode, StrakerTranslate::STATUS_PENDING);
      $this->messenger()->addStatus(t('The @locale translation for @entity_type %title is unlocked. Please check target status manually to get the translation status from the Straker Verify.', ['@locale' => $locale, '@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()->addError(t('Document @entity_type %title was not found.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The target unlock for @entity_type failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }

    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function checkTarget($doc_id, $locale) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');

    $entity = $translation_service->loadByDocumentId($doc_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot check target for @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot check target for @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }

    $drupal_language = $this->languageLocaleMapper->getConfigurableLanguageForLocale($locale);
    try {
      if ($translation_service->checkTargetStatus($entity, $drupal_language->id()) === StrakerTranslate::STATUS_READY) {
        $this->messenger()->addStatus(t('The @locale translation for @entity_type %title is ready for download.', ['@locale' => $locale, '@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
      else {
        $this->messenger()->addStatus(t('The @locale translation for @entity_type %title is still in progress.', ['@locale' => $locale, '@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()->addError(t('Document @entity_type %title was not found. Please upload again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateApiException $exc) {
      $this->messenger()->addError(t('The request for @entity_type translation status failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function upload($entity_type, $entity_id) {
    $entity = $this->entityTypeManager()->getStorage($entity_type)->load($entity_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');
    try {
      if ($translation_service->uploadDocument($entity)) {
        $this->messenger()->addStatus(t('@entity_type %title has been uploaded.', ['@entity_type' => ucfirst($entity->getEntityTypeId()), '%title' => $entity->label()]));
      }
      else {
        $this->messenger()->addError(t('The upload for @entity_type %title failed. Check your configuration and profile and try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
    }
    catch (StrakerTranslateDocumentAlreadyUploaded $exception) {
      $this->messenger()->addWarning(t('Document @entity_type %title was already uploaded and is being processed or is current.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslatePaymentRequiredException $exception) {
      $this->messenger()->addError(t('Community has been disabled. Please contact support@straker_translate.com to re-enable your community.'));
    }
    catch (StrakerTranslateProcessedWordsLimitException $exception) {
      $this->messenger()->addError(t('Processed word limit exceeded. Please contact your local administrator or Straker Translate Client Success (<a href=":link">@mail</a>) for assistance.', [':link' => 'mailto:sales@straker_translate.com', '@mail' => 'sales@straker_translate.com']));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The upload for @entity_type %title failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      $this->messenger()->addError($exception->getMessage());
      $this->messenger()->addError(t('The upload for @entity_type %title failed due to an API error. Please check the logs for more details.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      \Drupal::logger('straker_translate')->error('API Exception during upload for entity_type: @entity_type, title: %title. Exception: @message', [
        '@entity_type' => $entity->getEntityTypeId(),
        '%title' => $entity->label(),
        '@message' => $exception->getMessage(),
      ]);
    }
    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function confirm($doc_id) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');
    $entity = $translation_service->loadByDocumentId($doc_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    try {
      if ($translation_service->confirmDocument($entity)) {
        $this->messenger()->addStatus(t('@entity_type %title has been updated.', ['@entity_type' => ucfirst($entity->getEntityTypeId()), '%title' => $entity->label()]));
      }
      else {
        $this->messenger()->addError(t('The upload for @entity_type %title failed. Check your configuration and profile and try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
    }
    catch (StrakerTranslateDocumentAlreadyCompletedException $exc) {
      $this->messenger()
        ->addError(t('Document @entity_type %title was already processed.', [
          '@entity_type' => $entity->getEntityTypeId(),
          '%title' => $entity->label(),
        ]));
    }
    catch (StrakerTranslateDocumentArchivedException $exception) {
      $this->messenger()->addWarning(t('Document @entity_type %title has been archived. Uploading again.', [
        '@entity_type' => $entity->getEntityTypeId(),
        '%title' => $entity->label(),
      ]));
    }
    catch (StrakerTranslateDocumentLockedException $exception) {
      $this->messenger()->addError(t('Document @entity_type %title has a new version. The document id has been updated for all future interactions. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslatePaymentRequiredException $exception) {
      $this->messenger()->addError(t('Community has been disabled. Please contact support@straker_translate.com to re-enable your community.'));
    }
    catch (StrakerTranslateProcessedWordsLimitException $exception) {
      $this->messenger()->addError(t('Processed word limit exceeded. Please contact your local administrator or Straker Translate Client Success (<a href=":link">@mail</a>) for assistance.', [':link' => 'mailto:sales@straker_translate.com', '@mail' => 'sales@straker_translate.com']));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The update for @entity_type %title failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function update($entity_type, $entity_id) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');
    $entity = $this->entityTypeManager()->getStorage($entity_type)->load($entity_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot upload @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }
    try {
      if ($translation_service->uploadDocument($entity, TRUE)) {
        $this->messenger()->addStatus(t('@entity_type %title has been updated.', ['@entity_type' => ucfirst($entity->getEntityTypeId()), '%title' => $entity->label()]));
      }
      else {
        $this->messenger()->addError(t('The upload for @entity_type %title failed. Check your configuration and profile and try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
      }
    }
    catch (StrakerTranslateDocumentAlreadyUploaded $exception) {
      $this->messenger()->addWarning(t('Document @entity_type %title was already uploaded and is being processed or is current. If you wish to re-upload, please use the Forceful Re-upload option.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()
        ->addError(t('Document @entity_type %title was not found. Please upload again.', [
          '@entity_type' => $entity->getEntityTypeId(),
          '%title' => $entity->label(),
        ]));
    }
    catch (StrakerTranslateDocumentArchivedException $exception) {
      $this->messenger()->addWarning(t('Document @entity_type %title has been archived. Uploading again.', [
        '@entity_type' => $entity->getEntityTypeId(),
        '%title' => $entity->label(),
      ]));
    }
    catch (StrakerTranslateDocumentLockedException $exception) {
      $this->messenger()->addError(t('Document @entity_type %title has a new version. The document id has been updated for all future interactions. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslatePaymentRequiredException $exception) {
      $this->messenger()->addError(t('Community has been disabled. Please contact support@straker_translate.com to re-enable your community.'));
    }
    catch (StrakerTranslateProcessedWordsLimitException $exception) {
      $this->messenger()->addError(t('Processed word limit exceeded. Please contact your local administrator or Straker Translate Client Success (<a href=":link">@mail</a>) for assistance.', [':link' => 'mailto:sales@straker_translate.com', '@mail' => 'sales@straker_translate.com']));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The update for @entity_type %title failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  public function download($doc_id, $file_id, $langcode) {
    /** @var \Drupal\straker_translate\StrakerTranslateContentTranslationServiceInterface $translation_service */
    $translation_service = \Drupal::service('straker_translate.content_translation');

    $entity = $translation_service->loadByDocumentId($doc_id);
    if (!$entity) {
      // @todo log warning
      return $this->translationsPageRedirect($entity);
    }
    $bundleInfos = $this->entityTypeBundleInfo->getBundleInfo($entity->getEntityTypeId());
    if (!$entity->getEntityType()->isTranslatable() || !$bundleInfos[$entity->bundle()]['translatable']) {
      \Drupal::messenger()->addWarning(t('Cannot download @type %label. That @bundle_label is not enabled for translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]));
      return $this->translationsPageRedirect($entity);
    }
    if (!$this->straker_translateConfiguration->isEnabled($entity->getEntityTypeId(), $entity->bundle())) {
      $this->messenger()->addWarning(t('Cannot download @type %label. That @bundle_label is not enabled for Straker translation.',
        ['@type' => $bundleInfos[$entity->bundle()]['label'], '%label' => $entity->label(), '@bundle_label' => $entity->getEntityType()->getBundleLabel()]
      ));
      return $this->translationsPageRedirect($entity);
    }

    try {
      if ($translation_service->downloadDocument($entity, $file_id, $langcode)) {
        $this->messenger()->addStatus(t('The translation of @entity_type %title into @langcode has been downloaded.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label(), '@langcode' => $langcode]));
      }
      else {
        \Drupal::logger('straker_translate')->warning('Error happened trying to download (%entity_id,%revision_id).', ['%entity_id' => $entity->id(), '%revision_id' => $entity->getRevisionId()]);
        $this->messenger()->addError(t('The translation of @entity_type %title into @langcode failed to download.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label(), '@langcode' => $langcode]));
      }
    }
    catch (StrakerTranslateDocumentNotFoundException $exc) {
      $this->messenger()->addError(t('Document @entity_type %title was not found. Please upload again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateApiException $exception) {
      $this->messenger()->addError(t('The download for @entity_type %title failed. Please try again.', ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label()]));
    }
    catch (StrakerTranslateContentEntityStorageException $storage_exception) {
      \Drupal::logger('straker_translate')->error('The download for @entity_type %title failed because of the length of one field translation (%langcode) value: %table.',
        ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label(), '%langcode' => $langcode, '%table' => $storage_exception->getTable()]);
      $this->messenger()->addError(t('The download for @entity_type %title failed because of the length of one field translation (%langcode) value: %table.',
        ['@entity_type' => $entity->getEntityTypeId(), '%title' => $entity->label(), '%langcode' => $langcode, '%table' => $storage_exception->getTable()]));
    }
    return $this->translationsPageRedirect($entity);
  }

  /**
   *
   */
  protected function translationsPageRedirect(EntityInterface $entity) {
    $entity_type_id = $entity->getEntityTypeId();
    $uri = Url::fromRoute("entity.$entity_type_id.content_translation_overview", [$entity_type_id => $entity->id()]);
    $entity_type = $entity->getEntityType();
    if ($entity_type->hasLinkTemplate('canonical')) {
      return new RedirectResponse($uri->setAbsolute(TRUE)->toString());
    }
    else {
      return new RedirectResponse($this->request->getUri());
    }
  }

}
