<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\Platform\Document;

use Drupal\languagewire_translation_provider\Adapter\SystemInterface;
use Drupal\languagewire_translation_provider\Adapter\TMGMT\LanguageMapping;
use Drupal\languagewire_translation_provider\api\Libraries\Document\DraftDocument;
use Drupal\languagewire_translation_provider\Content\SanitizerInterface;
use Drupal\languagewire_translation_provider\Content\TMGMTContent;
use Drupal\languagewire_translation_provider\Domain\Document;
use Drupal\languagewire_translation_provider\Domain\DocumentStatus;
use Drupal\languagewire_translation_provider\Settings\JobSettings;

/**
 * Uploadable Platform Document.
 */
final class UploadableDocument extends DocumentBase {

  /**
   * Language Mapping.
   *
   * @var \Drupal\languagewire_translation_provider\Adapter\TMGMT\LanguageMapping
   */
  private LanguageMapping $languageMapping;

  /**
   * System.
   *
   * @var \Drupal\languagewire_translation_provider\Adapter\SystemInterface
   */
  private SystemInterface $system;

  /**
   * Content.
   *
   * @var \Drupal\languagewire_translation_provider\Content\TMGMTContent[]
   */
  private array $content;

  /**
   * Job Settings.
   *
   * @var \Drupal\languagewire_translation_provider\Settings\JobSettings
   */
  private JobSettings $jobSettings;

  /**
   * Constructs a new UploadableDocument object.
   *
   * @param \Drupal\languagewire_translation_provider\Domain\Document $document
   *   Document.
   * @param \Drupal\languagewire_translation_provider\Settings\JobSettings $jobSettings
   *   Job Settings.
   * @param \Drupal\languagewire_translation_provider\Adapter\TMGMT\LanguageMapping $languageMapping
   *   Language Mapping.
   * @param \Drupal\languagewire_translation_provider\Adapter\SystemInterface $system
   *   System.
   */
  public function __construct(Document $document, JobSettings $jobSettings, LanguageMapping $languageMapping, SystemInterface $system) {
    parent::__construct($document);
    $this->languageMapping = $languageMapping;
    $this->system = $system;
    $this->content = $document->getContent();
    $this->jobSettings = $jobSettings;
    $this->updateDomainDocument(FALSE);
  }

  /**
   * Get Document.
   */
  public function document(): Document {
    return $this->document;
  }

  /**
   * Get job item ID.
   */
  public function jobItemId(): int {
    return $this->document->getTmgmtItemId();
  }

  /**
   * Get language mapping.
   */
  public function getLanguageMapping(): LanguageMapping {
    return $this->languageMapping;
  }

  /**
   * Get title.
   */
  public function getTitle(): string {
    return $this->document->getTitle();
  }

  /**
   * Get content.
   *
   * @return \Drupal\languagewire_translation_provider\Content\TMGMTContent[]
   *   Content.
   */
  public function getContent(): array {
    return $this->content;
  }

  /**
   * To Platform Document.
   */
  public function toPlatformDocument(): DraftDocument {
    return $this->toUdfDocument()->toPlatformDraftDocument();
  }

  /**
   * Add Message.
   */
  public function addMessage(string $message): void {
    $this->document->addError($message);
  }

  /**
   * Sanitize Content.
   */
  public function sanitizeContent(SanitizerInterface $sanitizer): void {
    $this->content = array_map(function (TMGMTContent $content) use ($sanitizer) {
        return $content->sanitize($sanitizer);
    }, $this->content);
  }

  /**
   * Update Domain Document.
   */
  public function updateDomainDocument(bool $addMessage = TRUE): void {
    $this->document->setPlatformId(NULL);

    if (!$this->hasTranslatableContent()) {
      if ($addMessage) {
        $this->document->addError('This item will not be translated because all of its content has been excluded from translation.');
      }

      $this->document->setStatus(DocumentStatus::empty());
      return;
    }

    $this->document->setStatus(DocumentStatus::uploadingContent());
  }

  /**
   * Is Domain Document In Status.
   */
  public function isDomainDocumentInStatus(DocumentStatus $status): bool {
    return $this->document->getStatus()->equals($status);
  }

  /**
   * Has Translatable Content.
   */
  private function hasTranslatableContent(): bool {
    return !$this->toUdfDocument()->isEmpty();
  }

  /**
   * To UDF Document.
   */
  private function toUdfDocument(): UdfDocument {
    return new UdfDocument($this, $this->jobSettings, $this->system);
  }

}
