/// Utility class for codec-related operations.
///
/// Provides centralized codec name mappings, file extension lookups,
/// and display name formatting.
class CodecUtils {
  CodecUtils._();

  static String getSubtitleExtension(String? codec) {
    if (codec == null) return 'srt';

    switch (codec.toLowerCase()) {
      case 'subrip':
      case 'srt':
        return 'srt';
      case 'ass':
      case 'ssa':
        return 'ass';
      case 'webvtt':
      case 'vtt':
        return 'vtt';
      case 'mov_text':
        return 'srt';
      case 'pgs':
      case 'pgssub':
      case 'hdmv_pgs_subtitle':
        return 'sup';
      case 'dvd_subtitle':
      case 'dvdsub':
      case 'vobsub':
      case 'dvb_sub':
      case 'dvb_subtitle':
        return 'sub';
      default:
        return 'srt';
    }
  }

  static bool isTextSubtitleCodec(String? codec) {
    if (codec == null) return false;
    return switch (codec.toLowerCase()) {
      'srt' || 'subrip' || 'ass' || 'ssa' || 'webvtt' || 'vtt' || 'mov_text' => true,
      _ => false,
    };
  }

  /// Image-based (bitmap) subtitle codecs. Plex burns these into the video
  /// when the selected output transport cannot carry a bitmap subtitle
  /// rendition.
  static bool isImageSubtitleCodec(String? codec) {
    if (codec == null) return false;
    return switch (codec.toLowerCase()) {
      'pgs' ||
      'pgssub' ||
      'hdmv_pgs_subtitle' ||
      'dvd_subtitle' ||
      'dvdsub' ||
      'vobsub' ||
      'dvb_sub' ||
      'dvb_subtitle' => true,
      _ => false,
    };
  }

  /// Subtitle codecs Plex can deliver in a transcode. Text codecs can become
  /// segmented HLS WebVTT; image codecs can be burned into the video.
  static bool isTranscodableSubtitleCodec(String? codec) {
    return isTextSubtitleCodec(codec) || isImageSubtitleCodec(codec);
  }

  /// Formats a subtitle codec name to a user-friendly display format.
  ///
  /// Converts internal codec names like 'SUBRIP' to friendly names like 'SRT'.
  static String formatSubtitleCodec(String codec) {
    final upper = codec.toUpperCase();
    return switch (upper) {
      'SUBRIP' => 'SRT',
      'DVD_SUBTITLE' => 'DVD',
      'WEBVTT' => 'VTT',
      'HDMV_PGS_SUBTITLE' => 'PGS',
      'MOV_TEXT' => 'MOV',
      _ => upper,
    };
  }

  /// Formats a video codec name to a user-friendly display format.
  ///
  /// Converts internal codec names like 'hevc' to friendly names like 'HEVC'.
  static String formatVideoCodec(String codec) {
    final lower = codec.toLowerCase();
    return switch (lower) {
      'h264' || 'avc1' || 'avc' => 'H.264',
      'hevc' || 'h265' || 'hev1' => 'HEVC',
      'av1' => 'AV1',
      'vp8' => 'VP8',
      'vp9' => 'VP9',
      'mpeg2video' || 'mpeg2' => 'MPEG-2',
      'mpeg4' => 'MPEG-4',
      'vc1' => 'VC-1',
      _ => codec.toUpperCase(),
    };
  }

  /// Formats an audio channel count as a friendly layout name (2 → 'Stereo',
  /// 6 → '5.1'). Returns null when [channels] is null or not positive.
  static String? formatAudioChannels(int? channels) {
    if (channels == null || channels <= 0) return null;
    return switch (channels) {
      1 => 'Mono',
      2 => 'Stereo',
      3 => '3.0',
      4 => '4.0',
      5 => '4.1',
      6 => '5.1',
      7 => '6.1',
      8 => '7.1',
      _ => '${channels}ch',
    };
  }

  /// Formats an audio codec name to a user-friendly display format.
  static String formatAudioCodec(String codec) {
    final lower = codec.toLowerCase();
    return switch (lower) {
      'aac' => 'AAC',
      'ac3' => 'AC3',
      'eac3' || 'ec3' => 'E-AC3',
      'truehd' => 'TrueHD',
      'dts' => 'DTS',
      'dca' => 'DTS',
      'dtshd' || 'dts-hd' => 'DTS-HD',
      'flac' => 'FLAC',
      'mp3' || 'mp3float' => 'MP3',
      'opus' => 'Opus',
      'vorbis' => 'Vorbis',
      'pcm_s16le' || 'pcm_s24le' || 'pcm' => 'PCM',
      _ => codec.toUpperCase(),
    };
  }
}
