<?php
/**
 * Utility class for UUID generation.
 *
 * @package Ealab\Deployer
 */

namespace EaLab\WP_Deployer\vendor\Ealab\Deployer\Utility;

use EaLab\WP_Deployer\vendor\Dakwamine\Component\ComponentBasedObject;
use EaLab\WP_Deployer\vendor\Dakwamine\Component\Exception\UnmetDependencyException;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Exception\WpDeployException;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Tracking\ItemTracker\ItemTrackerBase;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Utility\UuidGenerator\PostsUuidGenerator;
use EaLab\WP_Deployer\vendor\Ealab\Deployer\Utility\UuidGenerator\UuidGeneratorBase;
use Throwable;

/**
 * Utility class for UUID generation.
 */
class Uuid extends ComponentBasedObject {
	/**
	 * The main UUID instance.
	 *
	 * @var Uuid|mixed|object|null
	 */
	private static $instance;

	/**
	 * Generates a UUID based on the content.
	 *
	 * @param string                   $local_id The item's local ID.
	 * @param ItemTrackerBase          $item_tracker The item tracker which owns the item.
	 * @param array<string,mixed>|null $options Options:
	 *     - "phase", string: One of the ItemTrackerBase::TRACK_MODE__* constants.
	 *
	 * @return string|null The generated UUID, or null if the UUID could not be generated.
	 *
	 * @throws WpDeployException Error on UUID generation.
	 *   It's not recommended to continue trying to build the UUID after this error
	 *   even as a fallback.
	 */
	public function generateHashFromContent(
		string          $local_id,
		ItemTrackerBase $item_tracker,
		?array          $options
	): ?string {
		$uuid_generator = $this->getUuidGeneratorByTracker( $item_tracker );

		return $uuid_generator->generateHashFromContent( $local_id, $item_tracker, $options );
	}

	/**
	 * Generates a version 4 (random) UUID.
	 *
	 * @return string
	 *   The generated UUID.
	 */
	public function generateUuidV4(): string {
		require_once ABSPATH . 'wp-includes/functions.php';

		return wp_generate_uuid4();
	}

	/**
	 * Gets the main instance of this class.
	 *
	 * @return static The main instance of this class.
	 *
	 * @throws UnmetDependencyException Cannot instantiate the class.
	 */
	public static function getInstance(): Uuid {
		if ( ! isset( static::$instance ) ) {
			static::$instance = static::getRootComponentByClassName( static::class, true );
		}

		return static::$instance;
	}

	/**
	 * Gets the UUID generator for the given item tracker.
	 *
	 * @param ItemTrackerBase $item_tracker Item tracker.
	 *
	 * @return UuidGeneratorBase The UUID generator.
	 *
	 * @throws Throwable Unmanageable exceptions.
	 * @throws WpDeployException Tracker errors.
	 */
	private function getUuidGeneratorByTracker( ItemTrackerBase $item_tracker ): UuidGeneratorBase {
		// TODO: make this configurable.
		switch ( $item_tracker->getTrackerId() ) {
			case 'posts':
				$uuid_generator_class_name = PostsUuidGenerator::class;
				break;

			default:
				$uuid_generator_class_name = UuidGeneratorBase::class;
				break;
		}

		return $this->getComponentByClassName( $uuid_generator_class_name, true );
	}

	/**
	 * Reset the tracking info for the given item tracker.
	 *
	 * @param ItemTrackerBase $item_tracker The item tracker to reset its tracking info.
	 *
	 * @throws Throwable Unmanageable errors.
	 * @throws WpDeployException Tracker errors.
	 */
	public function resetTracking( ItemTrackerBase $item_tracker ): void {
		$uuid_generator = $this->getUuidGeneratorByTracker( $item_tracker );

		$uuid_generator->resetTracking( $item_tracker );
	}
}
