<?php

namespace Drupal\acquia_contenthub_publisher\EventSubscriber\Cdf;

use Acquia\ContentHubClient\CDF\CDFObject;
use Drupal\acquia_contenthub\AcquiaContentHubEvents;
use Drupal\acquia_contenthub\Event\CreateCdfEntityEvent;
use Drupal\Core\Config\Entity\ConfigEntityInterface;
use Drupal\Core\Serialization\Yaml;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;

/**
 * Base class to update entity id with entity uuid within config entities.
 *
 * In certain cases when entity ids, which are unique to the site, are hardcoded
 * into the configuration and are being loaded on the subscribers, but the id
 * they represent most probably different. Therefore, we create the CDF with the
 * uuid instead and upon parsing the CDF we fetch the corresponding entity from
 * the database by the uuid and use its id.
 *
 * @see \Drupal\acquia_contenthub\AcquiaContentHubEvents::CREATE_CDF_OBJECT
 * @see \Drupal\acquia_contenthub_subscriber\EventSubscriber\ParseCdf\ConvertEntityUuidToIdParseCdfBase
 *
 * @package Drupal\acquia_contenthub_publisher\EventSubscriber\Cdf
 */
abstract class ConvertEntityIdToUuidCreateCdfEntityBase implements EventSubscriberInterface {

  /**
   * The entity.
   *
   * @var \Drupal\Core\Entity\EntityInterface
   */
  protected $entity;

  /**
   * The event dispatcher.
   *
   * @var \Symfony\Component\EventDispatcher\EventDispatcherInterface
   */
  protected $dispatcher;

  /**
   * ConvertEntityIdToUuidCreateCdfEntityBase constructor.
   *
   * @param \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher
   *   The event dispatcher.
   */
  public function __construct(EventDispatcherInterface $dispatcher) {
    $this->dispatcher = $dispatcher;
  }

  /**
   * {@inheritdoc}
   */
  public static function getSubscribedEvents(): array {
    $events[AcquiaContentHubEvents::CREATE_CDF_OBJECT][] =
      ['onCreateCdf', 0];
    return $events;
  }

  /**
   * Updates entity id with uuid.
   *
   * @param \Drupal\acquia_contenthub\Event\CreateCdfEntityEvent $event
   *   The create cdf entity event.
   */
  abstract public function replaceEntityIdWithUuid(CreateCdfEntityEvent $event): void;

  /**
   * Replace entity id with entity uuid.
   *
   * @param \Drupal\acquia_contenthub\Event\CreateCdfEntityEvent $event
   *   The create cdf entity event.
   */
  public function onCreateCdf(CreateCdfEntityEvent $event): void {
    $this->entity = $event->getEntity();
    if (!$this->entity instanceof ConfigEntityInterface) {
      return;
    }
    $this->replaceEntityIdWithUuid($event);
  }

  /**
   * Extracts decoded metadata from cdf.
   *
   * @param \Acquia\ContentHubClient\CDF\CDFObject $cdf
   *   The cdf object.
   *
   * @return array
   *   Decoded metadata.
   */
  public function getDecodedMetadata(CDFObject $cdf): array {
    $metadata = $cdf->getMetadata();
    return (array) Yaml::decode(base64_decode($metadata['data']));
  }

  /**
   * Encodes and updates metadata.
   *
   * @param \Acquia\ContentHubClient\CDF\CDFObject $cdf
   *   The create cdf entity event.
   * @param mixed $metadata_data
   *   Decoded metadata.
   */
  public function updateMetadata(CDFObject $cdf, $metadata_data): void {
    $metadata = $cdf->getMetadata();
    $metadata['data'] = base64_encode(Yaml::encode($metadata_data));
    $cdf->setMetadata($metadata);
  }

}
