<?php

declare(strict_types=1);

namespace Drupal\ffmpeg_media\Plugin\FFmpegOutput;

use Drupal\Core\StringTranslation\TranslatableMarkup;
use Drupal\ffmpeg_media\Attribute\FFmpegOutput;
use Drupal\ffmpeg_media\ValueObject\ConversionOptions;

/**
 * FLV v2 output format plugin for FFmpeg 8.0.
 *
 * FLV v2 (Enhanced FLV) adds support for:
 * - Multi-track audio and video streams
 * - Modern codecs: HEVC, VP9, AV1 (in addition to H.264)
 * - Enhanced RTMP compatibility for modern streaming
 * - Improved metadata handling.
 *
 * The -flvflags option enables FLV v2 specific features:
 * - add_keyframe_index: Adds keyframe index for seeking
 * - no_duration_filesize: Omits duration/filesize for live streams
 *
 * @see https://ffmpeg.org/ffmpeg-formats.html#flv
 */
#[FFmpegOutput(
  id: 'flv',
  label: new TranslatableMarkup('FLV v2 (Enhanced FLV)'),
  description: new TranslatableMarkup('FLV v2 container with modern codec support (HEVC, VP9, AV1) and enhanced RTMP compatibility. Requires FFmpeg 8.0+.'),
  extension: 'flv',
  mimeType: 'video/x-flv',
  supportedCodecs: ['h264', 'hevc', 'vp9', 'av1'],
  defaultCodec: 'h264',
  supportedAudioCodecs: ['aac', 'mp3'],
  weight: 20,
)]
final class FlvOutput extends FFmpegOutputBase {

  /**
   * FLV v2 flags for enhanced features.
   *
   * @var array<string>
   */
  private const array FLV_V2_FLAGS = [
    'add_keyframe_index',
  ];

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function buildArguments(ConversionOptions $options): array {
    $args = [
      '-f', 'flv',
    ];

    // Enable FLV v2 features via flvflags.
    $flvFlags = $this->buildFlvFlags($options);
    if ($flvFlags !== '') {
      $args[] = '-flvflags';
      $args[] = $flvFlags;
    }

    return $args;
  }

  /**
   * {@inheritdoc}
   */
  #[\Override]
  #[\NoDiscard]
  public function generateOutputPath(string $inputPath): string {
    $pathInfo = pathinfo($inputPath);
    $baseName = $pathInfo['filename'] ?? 'video';
    $directory = $pathInfo['dirname'] ?? '';

    return $directory . DIRECTORY_SEPARATOR . $baseName . '_converted.flv';
  }

  /**
   * Builds FLV v2 flags string for enhanced features.
   *
   * FLV v2 flags control advanced container features:
   * - add_keyframe_index: Improves seeking performance
   * - no_duration_filesize: For live streaming scenarios.
   *
   * @param \Drupal\ffmpeg_media\ValueObject\ConversionOptions $options
   *   Conversion options that may influence flag selection.
   *
   * @return string
   *   Flags string joined with '+' prefix, or empty string if no flags.
   */
  #[\NoDiscard]
  protected function buildFlvFlags(ConversionOptions $options): string {
    $flags = self::FLV_V2_FLAGS;

    // For live streaming scenarios, omit duration/filesize metadata.
    if ($this->isLiveStreamingMode($options)) {
      $flags[] = 'no_duration_filesize';
    }

    return '+' . implode('+', $flags);
  }

  /**
   * Determines if options indicate live streaming mode.
   *
   * Live streaming mode is detected when:
   * - extraArgs contain RTMP-related options
   * - No duration-based settings are present.
   *
   * @param \Drupal\ffmpeg_media\ValueObject\ConversionOptions $options
   *   Conversion options to analyze.
   *
   * @return bool
   *   TRUE if live streaming mode is indicated.
   */
  #[\NoDiscard]
  protected function isLiveStreamingMode(ConversionOptions $options): bool {
    /** @var mixed $arg */
    foreach ($options->extraArgs as $arg) {
      if (is_string($arg) && str_starts_with($arg, 'rtmp://')) {
        return TRUE;
      }
    }

    return FALSE;
  }

  /**
   * Builds arguments for multi-track audio support.
   *
   * FLV v2 supports multiple audio tracks, useful for:
   * - Multiple language audio tracks
   * - Commentary tracks
   * - Separate music/voice tracks.
   *
   * @param int $trackCount
   *   Number of audio tracks to map.
   *
   * @return array<string>
   *   FFmpeg arguments for multi-track audio mapping.
   */
  #[\NoDiscard]
  public function buildMultiTrackAudioArguments(int $trackCount): array {
    if ($trackCount <= 1) {
      return [];
    }

    $args = [];
    for ($i = 0; $i < $trackCount; $i++) {
      $args[] = '-map';
      $args[] = "0:a:{$i}";
    }

    return $args;
  }

  /**
   * Builds arguments for multi-track video support.
   *
   * FLV v2 supports multiple video tracks, useful for:
   * - Picture-in-picture scenarios
   * - Multiple camera angles
   * - Separate overlay tracks.
   *
   * @param int $trackCount
   *   Number of video tracks to map.
   *
   * @return array<string>
   *   FFmpeg arguments for multi-track video mapping.
   */
  #[\NoDiscard]
  public function buildMultiTrackVideoArguments(int $trackCount): array {
    if ($trackCount <= 1) {
      return [];
    }

    $args = [];
    for ($i = 0; $i < $trackCount; $i++) {
      $args[] = '-map';
      $args[] = "0:v:{$i}";
    }

    return $args;
  }

  /**
   * Gets codec-specific FLV v2 recommendations.
   *
   * Different codecs have different optimal settings for FLV v2:
   * - H.264: Best compatibility, works with legacy players
   * - HEVC: Better compression, requires FLV v2 aware players
   * - VP9: Good compression, limited player support
   * - AV1: Best compression, requires modern players.
   *
   * @param string $codecId
   *   The codec plugin ID.
   *
   * @return array{compatible: bool, notes: string}
   *   Compatibility information and usage notes.
   */
  #[\NoDiscard]
  public function getCodecRecommendations(string $codecId): array {
    return match ($codecId) {
      'h264' => [
        'compatible' => TRUE,
        'notes' => 'Maximum compatibility with all FLV players. Recommended for broad distribution.',
      ],
      'hevc' => [
        'compatible' => TRUE,
        'notes' => 'FLV v2 feature. Requires FFmpeg 8.0+ and compatible player. Better compression than H.264.',
      ],
      'vp9' => [
        'compatible' => TRUE,
        'notes' => 'FLV v2 feature. Limited player support. Good for web-based players.',
      ],
      'av1' => [
        'compatible' => TRUE,
        'notes' => 'FLV v2 feature. Best compression but requires newest players. Slowest encoding.',
      ],
      default => [
        'compatible' => FALSE,
        'notes' => 'Codec not supported by FLV v2 container.',
      ],
    };
  }

}
