<?php

declare(strict_types=1);

namespace Drupal\languagewire_translation_provider\api\Libraries\Document;

use Drupal\languagewire_translation_provider\api\Libraries\Content\DehydrationInterface;

/**
 * Document Reference Files.
 *
 * DocumentReferenceFiles represents a collection
 * of reference files associated with a document.
 *
 * Each one of these objects contains:
 * 1) An integer identifier of an uploaded and validated document.
 * 2) An array of integer identifiers of reference files.
 */
final class DocumentReferenceFiles implements DehydrationInterface, \Countable {
  /**
   * An array of document reference file relationships.
   *
   * @var array
   *   An array of arrays, each containing a document identifier
   *   and an array of reference file identifiers.
   */
  private array $relationships;

  /**
   * Constructs a new DocumentReferenceFiles object.
   */
  public function __construct() {
    $this->relationships = [];
  }

  /**
   * Adds a list of reference file IDs to the collection.
   *
   * @param int $documentId
   *   The identifier of the document.
   * @param int[] $referenceFileIds
   *   An array of reference file identifiers.
   */
  public function addDocumentReferenceFiles(int $documentId, array $referenceFileIds): void {
    $referenceFileIds = array_unique($referenceFileIds);

    if (empty($referenceFileIds)) {
      return;
    }

    $this->discardPreviousRelationshipIfExists($documentId);

    $relationship = [
      "documentId" => $documentId,
      "referenceFileIds" => $referenceFileIds,
    ];

    $this->relationships[] = $relationship;
  }

  /**
   * Returns an array of present document ids.
   *
   * @return int[]
   *   An array of document identifiers.
   */
  public function getDocumentIds(): array {
    return array_map(function ($relationship) {
        return $relationship["documentId"];
    }, $this->relationships);
  }

  /**
   * Returns an array of present reference files ids.
   *
   * @return int[]
   *   An array of reference file identifiers.
   */
  public function getUniqueReferenceFileIds(): array {
    $repeatedIds = array_map(function ($relationship) {
        return $relationship["referenceFileIds"];
    }, $this->relationships);

    $flattened = array_merge(...array_values($repeatedIds));

    return array_unique($flattened);
  }

  /**
   * {@inheritDoc}
   */
  public function dehydrate(): array {
    return array_map(function (array $relationship): \stdClass {
        return (object) $relationship;
    }, $this->relationships);
  }

  /**
   * Discard Previous Relationship If Exists .
   *
   * @param int $documentId
   *   The identifier of the document.
   */
  private function discardPreviousRelationshipIfExists(int $documentId): void {
    $this->relationships = array_filter($this->relationships, function (array $relationship) use ($documentId):bool {
       return $relationship["documentId"] != $documentId;
    });
  }

  /**
   * {@inheritDoc}
   */
  public function count(): int {
    return count($this->relationships);
  }

  /**
   * Returns true if there are no document reference.
   *
   * Returns true if there are no document reference
   * file relationships present.
   *
   * @return bool
   *   True if there are no document reference file
   *   relationships present.
   */
  public function isEmpty(): bool {
    return $this->count() == 0;
  }

}
