<?php

namespace Drupal\straker_translate;

use Drupal\Core\Entity\ContentEntityInterface;

/**
 * Service for managing Straker Translate content translations.
 */
interface StrakerTranslateContentTranslationServiceInterface {

  /**
   * Checks the source is uploaded correctly.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to check.
   *
   * @return bool
   *   True if the entity is uploaded successfully.
   */
  public function checkSourceStatus(ContentEntityInterface &$entity);

  /**
   * Gets the source status of the given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to check.
   *
   * @return int
   *   The status of the target translation (see Straker Translate class constants)
   */
  public function getSourceStatus(ContentEntityInterface &$entity);

  /**
   * Sets the translation status of a given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to change.
   * @param int $status
   *   Status of the translation. Use Straker Translate class constants.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   */
  public function setSourceStatus(ContentEntityInterface &$entity, $status);

  /**
   * Gets the current status of all the target translations.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to check.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   */
  public function checkTargetStatuses(ContentEntityInterface &$entity);

  /**
   * Gets the current status of the target translation.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to check.
   * @param string $langcode
   *   Translation language we want to check.
   *
   * @return bool
   *   True if the entity is uploaded succesfully.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   */
  public function checkTargetStatus(ContentEntityInterface &$entity, $langcode);

  /**
   * Gets the translation status of a given entity translation for a locale.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to get.
   * @param string $locale
   *   Straker translation language which we want to get.
   *
   * @return int
   *   The status of the target translation (see Straker Translate class constants)
   */
  public function getTargetStatus(ContentEntityInterface &$entity, $locale);

  /**
   * Gets the translation statuses of a given entity translation for all locales.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to get.
   *
   * @return array
   *   The statuses of the target translation keyed by langcode
   *   (see Straker Translate class constants for the values)
   */
  public function getTargetStatuses(ContentEntityInterface &$entity);

  /**
   * Sets the translation status of a given entity translation for a locale.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to change.
   * @param string $langcode
   *   Language code which we want to modify.
   * @param int $status
   *   Status of the translation. Use Straker Translate constants.
   * @param bool $save
   *   If FALSE, the entity is not saved yet. Defaults to TRUE.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   */
  public function setTargetStatus(ContentEntityInterface &$entity, $langcode, $status, $save = TRUE);

  /**
   * Sets the translation status of all translations of a given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to change.
   * @param int $status
   *   Status of the translation. Use Straker Translate constants.
   *
   * @return void
   */
  public function setTargetStatuses(ContentEntityInterface &$entity, $status);

  /**
   * Marks the translation status as dirty if they exist.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which status we want to change.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   */
  public function markTranslationsAsDirty(ContentEntityInterface &$entity);

  /**
   * Gets the document id in the Straker Translate platform for a given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which we want the document id.
   *
   * @return string
   *   The document id in the Straker Translate platform.
   */
  public function getDocumentId(ContentEntityInterface &$entity);

  /**
   * Sets the Straker Translate document id for a given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which we want to set a document id.
   * @param $doc_id
   *   The document id in the Straker Translate platform.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   The entity.
   */
  public function setDocumentId(ContentEntityInterface &$entity, $doc_id);

  /**
   * Gets the translation source locale of a given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which we want to get the source locale.
   *
   * @return string
   *   The locale as expected by the Straker Translate service.
   */
  public function getSourceLocale(ContentEntityInterface &$entity);

  /**
   * Returns the source data that will be uploaded to the Straker Translate service.
   *
   * Only those fields that have actual translatable text, and have marked for upload will
   * be included.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which we want the source data.
   * @param array &$visited
   *   The array of already visited entities, avoiding cycles and infinite loops.
   * @param string $revision_mode
   *   The mode to use for resolving the revision.
   *
   * @return array
   *   The source data extracted.
   */
  public function getSourceData(ContentEntityInterface &$entity, array &$visited = [], string $revision_mode = StrakerTranslateContentTranslationEntityRevisionResolver::RESOLVE_LATEST_TRANSLATION_AFFECTED);

  /**
   * Updates the entity hash.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity being checked.
   * @param array $precalculated_source_data
   *   The entity source data if we have already calculated that, avoiding doing
   *   it twice.
   *
   * @return void
   */
  public function updateEntityHash(ContentEntityInterface $entity, $precalculated_source_data = []);

  /**
   * Checks if the source entity data has changed from last time we uploaded it.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity being checked.
   *
   * @return bool
   *   TRUE if the entity has changed, false if not.
   */
  public function hasEntityChanged(ContentEntityInterface &$entity);

  /**
   * Uploads a document to the Straker Translate service.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity being uploaded.
   * @param bool $force_upload
   *   If TRUE, the document will be uploaded even if it has not changed.
   *
   * @return bool
   *   TRUE if the document was uploaded successfully, FALSE if not.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateProcessedWordsLimitException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslatePaymentRequiredException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentArchivedException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentLockedException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateApiException
   */
  public function uploadDocument(ContentEntityInterface $entity, $force_upload = FALSE);

  /**
   * Confrms a document to the Straker Translate service.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity being uploaded.
   *
   * @return bool
   *   TRUE if the document was uploaded successfully, FALSE if not.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateProcessedWordsLimitException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslatePaymentRequiredException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentArchivedException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentLockedException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateApiException
   */
  public function confirmDocument(ContentEntityInterface &$entity);

  /**
   * Downloads a document from the Straker Translate service for a given locale.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity being downloaded.
   * @param string $locale
   *   Straker translation language which we want to download.
   *
   * @return bool
   *   TRUE if the document was downloaded successfully, FALSE if not.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateApiException
   */
  public function downloadDocument(ContentEntityInterface &$entity, $file_id, $locale);

  /**
   * Downloads a document from the Straker Translate service for all available locales.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity being downloaded.
   *
   * @return bool
   *   TRUE if the document was downloaded successfully, FALSE if not.
   *
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateDocumentNotFoundException
   * @throws \Drupal\straker_translate\Exception\StrakerTranslateApiException
   */
  public function downloadDocuments(ContentEntityInterface &$entity);

  /**
   * Deletes all local metadata related to an entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity which we want to forget about.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   The entity.
   */
  public function deleteMetadata(ContentEntityInterface &$entity);

  /**
   * Loads the entity with the given document id.
   *
   * @param string $document_id
   *   The document id.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   The entity with the given document id.
   */
  public function loadByDocumentId($document_id);

  /**
   * Gets all local document ids.
   *
   * @return string[]
   *   Gets all local document ids.
   */
  public function getAllLocalDocumentIds();

  /**
   * Save the entity translation.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface &$entity
   *   The entity we want to save a translation for.
   * @param $locale
   *   The locale of the translation being saved.
   * @param $data
   *   The data being saved.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   Returns the entity which translations are saved.
   */
  public function saveTargetData(ContentEntityInterface &$entity, $locale, $data);

  /**
   * Updates the 'initial upload' time metadata to the current request time.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity which we want the document id.
   * @param int $timestamp
   *   The timestamp we want to store.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   Returns the entity.
   */
  public function setLastUploaded(ContentEntityInterface $entity, int $timestamp);

  /**
   * Updates the 'updated date' time metadata to the current request time.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity which we want the document id.
   * @param int $timestamp
   *   The timestamp we want to store.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   Returns the entity.
   */
  public function setLastUpdated(ContentEntityInterface $entity, int $timestamp);

  /**
   * Gets the 'initial upload' time metadata for the given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity which we want the document id.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   Returns the timestamp.
   */
  public function getLastUploaded(ContentEntityInterface $entity);

  /**
   * Gets the 'updated date' time metadata for the given entity.
   *
   * @param \Drupal\Core\Entity\ContentEntityInterface $entity
   *   The entity which we want the document id.
   *
   * @return \Drupal\Core\Entity\ContentEntityInterface
   *   Returns the timestamp.
   */
  public function getLastUpdated(ContentEntityInterface $entity);

}
