<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media;

use Drupal\Core\Cache\CacheBackendInterface;
use Drupal\Core\Extension\ModuleHandlerInterface;
use Drupal\Core\Plugin\DefaultPluginManager;
use Drupal\ffmpeg_media\Attribute\FFmpegProcessor;
use Drupal\ffmpeg_media\Plugin\FFmpegProcessor\FFmpegProcessorInterface;

/**
 * Plugin manager for FFmpeg processor plugins.
 *
 * @internal Runtime service, not part of the supported contrib extension API.
 */
class FFmpegProcessorPluginManager extends DefaultPluginManager {

  /**
   * Constructs an FFmpegProcessorPluginManager object.
   *
   * @param \Traversable $namespaces
   *   An object that implements \Traversable which contains the root paths
   *   keyed by the corresponding namespace.
   * @param \Drupal\Core\Cache\CacheBackendInterface $cache_backend
   *   Cache backend instance to use.
   * @param \Drupal\Core\Extension\ModuleHandlerInterface $module_handler
   *   The module handler to invoke alter hooks.
   */
  public function __construct(
    \Traversable $namespaces,
    CacheBackendInterface $cache_backend,
    ModuleHandlerInterface $module_handler,
  ) {
    parent::__construct(
      'Plugin/FFmpegProcessor',
      $namespaces,
      $module_handler,
      FFmpegProcessorInterface::class,
      FFmpegProcessor::class,
    );

    $this->alterInfo('ffmpeg_processor_info');
    $this->setCacheBackend($cache_backend, 'ffmpeg_processor_plugins');
  }

  /**
   * Gets all available processor plugins.
   *
   * @return array<\Drupal\ffmpeg_media\Plugin\FFmpegProcessor\FFmpegProcessorInterface>
   *   Array of available processor instances.
   */
  #[\NoDiscard]
  public function getAvailableProcessors(): array {
    $processors = [];
    foreach ($this->getDefinitions() as $id => $definition) {
      $processor = $this->createInstance($id);
      if ($processor instanceof FFmpegProcessorInterface && $processor->isAvailable()) {
        $processors[$id] = $processor;
      }
    }
    return $processors;
  }

  /**
   * Gets processors by output type.
   *
   * @param string $outputType
   *   Output type (e.g., 'image', 'text', 'video').
   *
   * @return array<\Drupal\ffmpeg_media\Plugin\FFmpegProcessor\FFmpegProcessorInterface>
   *   Array of matching processor instances.
   */
  #[\NoDiscard]
  public function getProcessorsByOutputType(string $outputType): array {
    $processors = [];
    foreach ($this->getAvailableProcessors() as $id => $processor) {
      if ($processor->getOutputType() === $outputType) {
        $processors[$id] = $processor;
      }
    }
    return $processors;
  }

  /**
   * Gets processor options for form select.
   *
   * @param string|null $outputType
   *   Optional output type to filter by.
   *
   * @return array<string, string>
   *   Array of processor labels keyed by ID.
   */
  #[\NoDiscard]
  public function getProcessorOptions(?string $outputType = NULL): array {
    $processors = $outputType !== NULL
      ? $this->getProcessorsByOutputType($outputType)
      : $this->getAvailableProcessors();

    $options = [];
    foreach ($processors as $id => $processor) {
      $options[$id] = $processor->getLabel();
    }
    return $options;
  }

}
