<?php

namespace Drupal\acquia_contenthub_translations\EntityHandler;

use Drupal\Core\Config\Config;

/**
 * Provides an interface to access handler information regarding entities.
 */
class HandlerRegistry {

  /**
   * Unspecified handler.
   */
  public const UNSPECIFIED = 'unspecified';

  /**
   * Path to unspecified list in acquia_contenthub_translation config.
   */
  public const UNSPECIFIED_CONFIG_KEY = 'nt_entity_registry.unspecified';

  /**
   * Path to handler mapping in acquia_contenthub_translation config.
   */
  public const ENTITY_HANDLERS_CONFIG_KEY = 'nt_entity_registry.handler_mapping';

  /**
   * Path to overridden handler mapping in acquia_contenthub_translation config.
   */
  public const OVERRIDDEN_HANDLERS_CONFIG_KEY = 'nt_override_registry';

  /**
   * Default settings for specific non-translatable files.
   *
   * @var string[]
   */
  protected $default = [
    // File entities are flexible in terms of their language. They are created
    // in the site's default language.
    'file:file' => 'flexible',
    // The redirect entity applies for every language if langcode is und.
    // It can be safely removed if the langcode is specified, because the rest
    // of the translations were already removed, the rest of the version are
    // residual.
    'redirect:redirect' => 'removable',
    // Path aliases are similar to redirect entities, in a way that on every
    // translation a new is being created.
    'path_alias:path_alias' => 'removable',
  ];

  /**
   * The acquia_contenthub_translations config.
   *
   * @var \Drupal\Core\Config\Config
   */
  protected $config;

  /**
   * Constructs a new object.
   *
   * @param \Drupal\Core\Config\Config $config
   *   The acquia_contenthub_translations config.
   */
  public function __construct(Config $config) {
    $this->config = $config;
  }

  /**
   * Returns the handler id for an entity.
   *
   * @param string $entity_type
   *   The entity type to check.
   * @param string $bundle
   *   Bundle to check.
   *
   * @return string
   *   The handler id.
   */
  public function getHandlerIdFor(string $entity_type, string $bundle): string {
    $collection = array_merge($this->default, $this->getUnspecified(), $this->getHandlerMapping());
    return $collection["$entity_type:$bundle"] ?? $collection["$entity_type:$entity_type"] ?? static::UNSPECIFIED;
  }

  /**
   * Returns unspecified entities.
   *
   * @return array
   *   The unspecified registry.
   */
  public function getUnspecified(): array {
    return $this->config->get(static::UNSPECIFIED_CONFIG_KEY) ?? [];
  }

  /**
   * Adds a new element to the unspecified list.
   *
   * @param string $entity_type
   *   The entity type to register.
   * @param string $bundle
   *   Bundle.
   */
  public function addToUnspecified(string $entity_type, string $bundle): void {
    $current = $this->getUnspecified();
    $current["$entity_type:$bundle"] = static::UNSPECIFIED;
    $this->config->set(static::UNSPECIFIED_CONFIG_KEY, $current)->save();
  }

  /**
   * Returns if the given entity is unspecified.
   *
   * @param string $entity_type
   *   The entity type id.
   * @param string $bundle
   *   Bundle.
   *
   * @return bool
   *   TRUE if the entity is not specified.
   */
  public function isUnspecified(string $entity_type, string $bundle): bool {
    $unspecified = $this->getUnspecified();
    return isset($unspecified["$entity_type:$bundle"]) ||
      isset($unspecified["$entity_type:$entity_type"]);
  }

  /**
   * Adds entities to the handler mapping list.
   *
   * @param string $entity_type
   *   The entity type to add.
   * @param string $bundle
   *   Bundle to add.
   * @param string $handler_id
   *   The handler id to assign to the entity.
   */
  public function addEntityToRegistry(string $entity_type, string $bundle, string $handler_id): void {
    $current = $this->getHandlerMapping();
    $current = array_merge($current, ["$entity_type:$bundle" => $handler_id]);
    $this->config->set(static::ENTITY_HANDLERS_CONFIG_KEY, $current)->save();
  }

  /**
   * Adds entities to the overridden entities list.
   *
   * @param string $entity_type
   *   The entity type to add.
   * @param string $bundle
   *   Bundle to add.
   */
  public function addEntityToOverriddenRegistry(string $entity_type, string $bundle): void {
    $current = $this->getOverriddenHandlerMapping();
    $current[] = "$entity_type:$bundle";
    $this->config->set(static::OVERRIDDEN_HANDLERS_CONFIG_KEY, array_unique($current))->save();
  }

  /**
   * Returns the current entity mapping.
   *
   * @return array
   *   The handler mapping.
   */
  public function getHandlerMapping(): array {
    return $this->config->get(static::ENTITY_HANDLERS_CONFIG_KEY) ?? [];
  }

  /**
   * Returns the current overridden handler mapping.
   *
   * @return array
   *   Overridden handler mapping.
   */
  public function getOverriddenHandlerMapping(): array {
    return $this->config->get(static::OVERRIDDEN_HANDLERS_CONFIG_KEY) ?? [];
  }

}
