<?php

namespace Drupal\acquia_contenthub_publisher\Libs;

use Drupal\Core\Config\Config;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Config\ImmutableConfig;

/**
 * Base class for configuration settings.
 */
abstract class ConfigSettingsBase {

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

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

  /**
   * The configuration factory.
   *
   * @var \Drupal\Core\Config\ConfigFactoryInterface
   */
  protected ConfigFactoryInterface $configFactory;

  /**
   * ConfigSettingsBase constructor.
   *
   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
   *   The configuration factory.
   */
  public function __construct(ConfigFactoryInterface $config_factory) {
    $this->configFactory = $config_factory;
    $this->config = $this->getEditableConfig();
    $this->values = $this->config->getRawData();
  }

  /**
   * Persists current state.
   */
  public function save(): void {
    $this->config->setData($this->values);
    $this->config->save();
    $this->values = [];
  }

  /**
   * 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->getImmutableConfig()->get($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;
  }

  /**
   * Provides editable settings.
   *
   * @return \Drupal\Core\Config\Config
   *   Config object.
   */
  protected function getEditableConfig(): Config {
    return $this->configFactory->getEditable($this->getConfigName());
  }

  /**
   * Provides non-editable settings.
   *
   * @return \Drupal\Core\Config\ImmutableConfig
   *   Non-editable config object
   */
  protected function getImmutableConfig(): ImmutableConfig {
    return $this->configFactory->get($this->getConfigName());
  }

  /**
   * Get the configuration name.
   *
   * @return string
   *   The configuration name.
   */
  abstract protected function getConfigName(): string;

}
