<?php

namespace Drupal\acquia_contenthub_subscriber\Libs;

use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\user\UserInterface;

/**
 * An implementation of the user syndication settings using drupal config.
 *
 * This class is the primary way to manage user syndication settings. Therefore,
 * the underlying method of how configuration is managed is abstracted away.
 */
class UserSyndicationSettings implements UserSyndicationSettingsInterface {

  /**
   * The name of the drupal configuration.
   */
  private const CONFIG_NAME = 'acquia_contenthub_subscriber.user_syndication';

  /**
   * The plugin manager for entity types.
   *
   * @var \Drupal\Core\Entity\EntityTypeManagerInterface
   */
  private EntityTypeManagerInterface $entityTypeManager;

  /**
   * The related configuration object.
   *
   * @var \Drupal\Core\Config\Config
   */
  private Config $config;

  /**
   * The configuration values.
   *
   * @var array
   */
  private array $values;

  /**
   * Constructs this object.
   *
   * @param \Drupal\Core\Entity\EntityTypeManagerInterface $etm
   *   The plugin manager for entity types.
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   */
  public function __construct(EntityTypeManagerInterface $etm, ConfigFactoryInterface $config_factory) {
    $this->entityTypeManager = $etm;
    $this->config = $config_factory->getEditable(self::CONFIG_NAME);
    $this->values = $this->config->getRawData();
  }

  /**
   * {@inheritdoc}
   */
  public function isUserSyndicationDisabled(): bool {
    return $this->getConfig('disable_user_syndication', FALSE);
  }

  /**
   * {@inheritdoc}
   */
  public function isUserRoleSyndicationDisabled(): bool {
    return $this->getConfig('disable_user_role_syndication', FALSE);
  }

  /**
   * {@inheritdoc}
   */
  public function toggleUserSyndication(bool $disabled): void {
    $this->setConfig('disable_user_syndication', $disabled);
  }

  /**
   * {@inheritdoc}
   */
  public function toggleUserRoleSyndication(bool $disabled): void {
    $this->setConfig('disable_user_role_syndication', $disabled);
  }

  /**
   * {@inheritdoc}
   */
  public function setProxyUser(int $id): void {
    $user = $this->entityTypeManager->getStorage('user')->load($id);
    if (!$user) {
      return;
    }
    $this->setConfig('proxy_user', $id);
  }

  /**
   * {@inheritdoc}
   */
  public function resetProxyUser(): void {
    $this->setConfig('proxy_user', NULL);
  }

  /**
   * {@inheritdoc}
   */
  public function getProxyUser(): ?UserInterface {
    $user_id = $this->getConfig('proxy_user');
    if (!$user_id) {
      return NULL;
    }
    return $this->entityTypeManager->getStorage('user')->load($user_id);
  }

  /**
   * {@inheritdoc}
   */
  public function save(): void {
    $this->config->setData($this->values);
    $this->config->save();
  }

  /**
   * Returns a config value based on the provided key.
   *
   * @param string $key
   *   The identifier of the value.
   * @param mixed $default_value
   *   The value if the key had no corresponding value.
   *
   * @return mixed
   *   The value on the specified key or provided default value.
   */
  protected function getConfig(string $key, $default_value = NULL) {
    return $this->values[$key] ?? $default_value;
  }

  /**
   * Sets a configuration value based on the identifier.
   *
   * @param string $key
   *   The key to set the value at.
   * @param mixed $value
   *   The value to set.
   */
  protected function setConfig(string $key, $value): void {
    $this->values[$key] = $value;
  }

}
