<?php
/**
 * Base class for config providers.
 *
 * @package Ealab\Deployer
 */

namespace EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\Config;

use EaLab\WP_Deployer\vendor\Dakwamine\Component\ComponentBasedObject;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Exception\WpDeployException;

/**
 * Base class for config providers.
 */
abstract class ConfigProviderBase extends ComponentBasedObject {
	/**
	 * The manager holding this instance.
	 *
	 * @var ConfigProviderManagerBase
	 */
	private ConfigProviderManagerBase $config_provider_manager;

	/**
	 * The collected config.
	 *
	 * @var array|null
	 */
	protected ?array $config = null;

	/**
	 * Collects the config.
	 *
	 * @return array<string,array>|null The config. If null is returned, it means that the config is unset.
	 *
	 * @throws WpDeployException If the provider could not collect the config.
	 */
	public function collect(): ?array {
		// Implement this for config collection.
		$this->config = null;

		return $this->config;
	}

	/**
	 * Gets the config without collecting it.
	 *
	 * @return array<string,array>|null The config.
	 *     If null is returned, you may want to collect the config
	 *     by calling the collect() method.
	 */
	public function getConfig(): ?array {
		return $this->config;
	}

	/**
	 * Inits this instance with the given options.
	 *
	 * @param ConfigProviderManagerBase $config_provider_manager The manager holding this instance.
	 * @param array<string,mixed>|null  $options Options array for initialization.
	 *
	 * @throws WpDeployException If the provider could not be initialized.
	 */
	public function init( ConfigProviderManagerBase $config_provider_manager, ?array $options = null ): void {
		$this->config_provider_manager = $config_provider_manager;
	}

	/**
	 * Saves the config to the expected location.
	 *
	 * Implement this method to save the config in the expected locations (repository, database, etc.).
	 *
	 * @param array|null $config The config to save. Passing null should unset the config.
	 */
	protected function saveConfig( ?array $config ): void {
		// Implement this to save the config.
	}

	/**
	 * Sets the config. A normalization pass is done on the given config before saving it.
	 *
	 * @param array|null $config The config to set. Passing null should unset the config.
	 * @param bool       $requires_validation Set to true if the passed value requires validation. Defaults to true.
	 *
	 * @throws WpDeployException If the config is invalid. The message contains the error.
	 */
	public function setConfig( ?array &$config, bool $requires_validation = true ): void {
		( null !== $config ) && $requires_validation && $this->config_provider_manager->validateConfig( $config );

		( null !== $config ) && $this->config_provider_manager->normalizeConfig( $config );

		$this->saveConfig( $config );

		$this->config = $config;
	}
}
