<?php
/**
 * Recording launch compiler router.
 *
 * @package ScheduledChanges
 */

namespace ScheduledChanges\Recording;

use ScheduledChanges\Domain\Recording\RecordingSession;
use ScheduledChanges\Domain\Shared\NamedTimezone;

/**
 * Routes launch compilation by the persisted neutral source type.
 */
final class RecordingLaunchCompilerRouter implements RecordingLaunchCompilerContract {
	/**
	 * @var array<string,RecordingLaunchCompilerContract>
	 */
	private array $routes;

	/**
	 * @param array<string,RecordingLaunchCompilerContract> $routes Compilers keyed by source type.
	 */
	public function __construct( array $routes ) {
		$this->routes = $routes;
	}

	/**
	 * Returns a new router with additional source-type routes.
	 *
	 * @param string[] $source_types Source types owned by the compiler.
	 */
	public function withCompiler( array $source_types, RecordingLaunchCompilerContract $compiler ): self {
		$routes = $this->routes;

		foreach ( $source_types as $source_type ) {
			$routes[ $source_type ] = $compiler;
		}

		return new self( $routes );
	}

	public function compile(
		RecordingSession $session,
		array $diff,
		array $selected_change_ids,
		string $launch_name,
		string $launch_description,
		NamedTimezone $timezone,
		int $actor_id
	): RecordingFinalizationResult {
		$source_type = $session->sourceType();

		if ( ! isset( $this->routes[ $source_type ] ) ) {
			throw new \RuntimeException( 'The recording launch compiler for this session is unavailable.' );
		}

		return $this->routes[ $source_type ]->compile(
			$session,
			$diff,
			$selected_change_ids,
			$launch_name,
			$launch_description,
			$timezone,
			$actor_id
		);
	}
}
