<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Service;

use Drupal\ffmpeg_media\FFmpegCodecPluginManager;
use Drupal\ffmpeg_media\FFmpegOutputPluginManager;
use Drupal\ffmpeg_media\FFmpegProcessorPluginManager;
use Drupal\ffmpeg_media\Plugin\FFmpegCodec\FFmpegCodecInterface;
use Drupal\ffmpeg_media\Plugin\FFmpegOutput\FFmpegOutputInterface;
use Drupal\ffmpeg_media\Plugin\FFmpegProcessor\FFmpegProcessorInterface;

/**
 * Factory for FFmpeg plugin managers and plugin instance creation.
 *
 * @internal
 */
final class PluginFactory implements PluginFactoryInterface {

  /**
   * Constructs a PluginFactory object.
   *
   * @param \Drupal\ffmpeg_media\FFmpegCodecPluginManager $codecManager
   *   Codec plugin manager.
   * @param \Drupal\ffmpeg_media\FFmpegOutputPluginManager $outputManager
   *   Output plugin manager.
   * @param \Drupal\ffmpeg_media\FFmpegProcessorPluginManager $processorManager
   *   Processor plugin manager.
   */
  public function __construct(
    private readonly FFmpegCodecPluginManager $codecManager,
    private readonly FFmpegOutputPluginManager $outputManager,
    private readonly FFmpegProcessorPluginManager $processorManager,
  ) {}

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getCodecManager(): FFmpegCodecPluginManager {
    return $this->codecManager;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getOutputManager(): FFmpegOutputPluginManager {
    return $this->outputManager;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function getProcessorManager(): FFmpegProcessorPluginManager {
    return $this->processorManager;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function createCodecInstance(string $pluginId, array $configuration = []): FFmpegCodecInterface {
    $instance = $this->codecManager->createInstance($pluginId, $configuration);
    if (!$instance instanceof FFmpegCodecInterface) {
      throw new \UnexpectedValueException(sprintf(
        'Expected %s, got %s for plugin %s.',
        FFmpegCodecInterface::class,
        get_debug_type($instance),
        $pluginId,
      ));
    }
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function createOutputInstance(string $pluginId, array $configuration = []): FFmpegOutputInterface {
    $instance = $this->outputManager->createInstance($pluginId, $configuration);
    if (!$instance instanceof FFmpegOutputInterface) {
      throw new \UnexpectedValueException(sprintf(
        'Expected %s, got %s for plugin %s.',
        FFmpegOutputInterface::class,
        get_debug_type($instance),
        $pluginId,
      ));
    }
    return $instance;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function createProcessorInstance(string $pluginId, array $configuration = []): FFmpegProcessorInterface {
    $instance = $this->processorManager->createInstance($pluginId, $configuration);
    if (!$instance instanceof FFmpegProcessorInterface) {
      throw new \UnexpectedValueException(sprintf(
        'Expected %s, got %s for plugin %s.',
        FFmpegProcessorInterface::class,
        get_debug_type($instance),
        $pluginId,
      ));
    }
    return $instance;
  }

}
