<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\api\Libraries\Content\Udf;

/**
 * Document Frame.
 *
 * Document consists of frames. A frame contains text,
 * a comment (optional) and arbitrary metadata (also optional).
 *
 * For example, we have a CMS page with two fields:
 * page title and page content.
 *
 * We want to translate this page,
 * therefore we would create a document with 2 frames.
 * One frame for the page title and a second one for the page
 * content.
 * Most likely the page and its fields are stored somehow in a database.
 * Assuming that each page and content field are
 * stored with some kind unique ID we could pass that ID inside a Frame
 * as {@link Metadata} to the server. When the
 * text is translated, we receive the original metadata of the source text.
 *
 * Example:
 * ```
 * $page = PageCollection::get($pageId);
 * $metadata = new Metadata(['title_id' => $page->getTitle()->getId()]);
 * $titleFrame = new Frame(
 *   (string)$page->getTitle(),
 *   sprintf('Page %d title %d', $page->getId(), $page->getTitle()->getId()),
 *   $metadata
 * );
 * // create similar frame for page content...
 * ```
 */
final class Frame implements FrameInterface {
  /**
   * Frame text.
   *
   * @var string
   */
  private string $text;
  /**
   * Frame comment.
   *
   * @var string
   */
  private string $comment;
  /**
   * Frame metadata.
   *
   * @var \Drupal\languagewire_translation_provider\api\Libraries\Content\Udf\MetadataInterface
   */
  private MetadataInterface $metadata;

  /**
   * Constructs a new Frame object.
   *
   * @param string $text
   *   Frame text.
   * @param string $comment
   *   Frame comment.
   * @param \Drupal\languagewire_translation_provider\api\Libraries\Content\Udf\MetadataInterface|null $metadata
   *   Frame metadata.
   */
  public function __construct(string $text = '', string $comment = '', ?MetadataInterface $metadata = NULL) {
    $this->text = $text;
    $this->comment = $comment;
    $this->metadata = $metadata ?? new Metadata();
  }

  /**
   * {@inheritdoc}
   */
  public function getText(): string {
    return $this->text;
  }

  /**
   * {@inheritdoc}
   */
  public function getComment(): string {
    return $this->comment;
  }

  /**
   * {@inheritdoc}
   */
  public function getMetadata(): MetadataInterface {
    return $this->metadata;
  }

  /**
   * Dehydrates object data into a serializable format.
   *
   * @return array
   *   Dehydrated object data.
   */
  public function dehydrate(): array {
    $frame = ['text' => $this->text];

    if ($this->comment !== '') {
      $frame['comment'] = $this->comment;
    }

    if (isset($this->metadata)) {
      $frame['metadata'] = $this->metadata->dehydrate();
    }

    return $frame;
  }

  /**
   * Allows object to be used in a string context.
   *
   * For example
   * <pre>
   * $frame = new Frame('My text');
   * echo $frame;
   * </pre>.
   *
   * @return string
   *   Frame text.
   */
  public function __toString(): string {
    return $this->text;
  }

}
