/**
 * A Jellyfin DeviceProfile describing what this browser client can play.
 *
 * The server uses this to decide direct-play vs direct-stream vs transcode
 * and to choose codecs/containers that browsers can decode.
 *
 * Strategy mirrors jellyfin-web:
 *   - DirectPlay any mp4/m4v with codecs the browser advertises support for.
 *   - Transcode (or stream-copy via remux) into fMP4 over HLS, served through
 *     hls.js + MSE. Listing multiple VideoCodec values on the TranscodingProfile
 *     lets the server pick the source codec when it's already compatible -
 *     that's the difference between "remux a file in 2 seconds" and "re-encode
 *     every frame in real time". A Raspberry Pi can do the former; nothing in
 *     this codebase makes it do the latter unless the source is genuinely
 *     incompatible.
 *
 * MaxStreamingBitrate is intentionally high - we'd rather direct-stream the
 * source bitrate as-is than throttle it. The server only honours the cap when
 * a transcode is actually required.
 */

/**
 * Best-effort runtime probes for codec support in MSE. Browsers report this
 * accurately for VP9/AV1; HEVC support is hardware-gated and can vary even
 * on the same browser version, so we trust whatever isTypeSupported says.
 */
function canPlayInMse(mime: string): boolean {
  try {
    return typeof MediaSource !== 'undefined' && MediaSource.isTypeSupported(mime)
  } catch {
    return false
  }
}

function supportedVideoCodecs(): string[] {
  const codecs: string[] = ['h264'] // Universally supported in MSE
  if (canPlayInMse('video/mp4; codecs="hev1.1.6.L93.B0"') ||
      canPlayInMse('video/mp4; codecs="hvc1.1.6.L93.B0"')) {
    codecs.push('hevc')
  }
  if (canPlayInMse('video/mp4; codecs="vp09.00.10.08"')) {
    codecs.push('vp9')
  }
  if (canPlayInMse('video/mp4; codecs="av01.0.04M.08"')) {
    codecs.push('av1')
  }
  return codecs
}

/**
 * HDR support detection. Probes for the codec strings the major HDR
 * formats use:
 *   - HDR10 / HLG via HEVC main10 level 5.1 (`hvc1.2.4.L153.B0`) or VP9.2
 *     (`vp09.02.10.10.01.09.16.09.00`)
 *   - Dolby Vision via the `dvh1.05.06` codec string
 * When a format is detected we add it to the `VideoRangeType` matrix on
 * the corresponding CodecProfile so the server direct-plays HDR content
 * instead of falling back to a tone-mapped SDR transcode.
 */
function supportedVideoRanges(): string {
  const ranges = ['SDR']
  if (
    canPlayInMse('video/mp4; codecs="hvc1.2.4.L153.B0"') ||
    canPlayInMse('video/mp4; codecs="hev1.2.4.L153.B0"') ||
    canPlayInMse('video/webm; codecs="vp09.02.10.10.01.09.16.09.00"')
  ) {
    ranges.push('HDR10', 'HLG')
  }
  if (
    canPlayInMse('video/mp4; codecs="dvh1.05.06"') ||
    canPlayInMse('video/mp4; codecs="dvhe.05.06"')
  ) {
    ranges.push('DOVI', 'DOVIWithHDR10', 'DOVIWithHLG', 'DOVIWithSDR')
  }
  return ranges.join('|')
}

export function browserDeviceProfile(audioPassthrough = false) {
  const videoCodecs = supportedVideoCodecs()
  const videoCodecsCsv = videoCodecs.join(',')
  const videoRanges = supportedVideoRanges()

  return {
    Name: 'Jellybloom Browser Client',
    MaxStreamingBitrate: 120_000_000,
    MaxStaticBitrate: 100_000_000,
    MusicStreamingTranscodingBitrate: 384_000,

    DirectPlayProfiles: [
      {
        Container: 'mp4,m4v',
        Type: 'Video',
        VideoCodec: videoCodecsCsv,
        AudioCodec: audioPassthrough
          ? 'aac,mp3,ac3,eac3,flac,opus,truehd,dts'
          : 'aac,mp3,ac3,eac3,flac,opus',
      },
      {
        Container: 'webm',
        Type: 'Video',
        VideoCodec: 'vp8,vp9,av1',
        AudioCodec: 'opus,vorbis',
      },
    ],

    TranscodingProfiles: [
      {
        // fMP4 over HLS. Listing the full supported codec set lets the server
        // stream-copy (remux only) when the source already matches one of
        // them - that's what makes h264-in-mkv "play instantly" instead of
        // burning CPU. The browser plays this through MSE via hls.js.
        Container: 'mp4',
        Type: 'Video',
        VideoCodec: videoCodecsCsv,
        AudioCodec: 'aac,mp3',
        Protocol: 'hls',
        Context: 'Streaming',
        MaxAudioChannels: '6',
        MinSegments: 1,
        BreakOnNonKeyFrames: true,
      },
      {
        Container: 'aac',
        Type: 'Audio',
        AudioCodec: 'aac',
        Context: 'Streaming',
        Protocol: 'http',
        MaxAudioChannels: '2',
      },
    ],

    ContainerProfiles: [],
    CodecProfiles: [
      // Bound h264 to profiles/levels MSE actually decodes - avoids the
      // server stream-copying high-10 or level 5.2 footage that the browser
      // would silently refuse.
      {
        Type: 'Video',
        Codec: 'h264',
        Conditions: [
          {
            Condition: 'EqualsAny',
            Property: 'VideoProfile',
            Value: 'high|main|baseline|constrained baseline|high 10',
            IsRequired: false,
          },
          {
            Condition: 'LessThanEqual',
            Property: 'VideoLevel',
            Value: '52',
            IsRequired: false,
          },
        ],
      },
      // HEVC: cap at main / main10 + level 5.1 - matches what hardware
      // decoders on most consumer GPUs can chew through. VideoRangeType
      // advertises whichever HDR formats the browser actually supports so
      // the server direct-plays HDR sources instead of tone-mapping to SDR.
      {
        Type: 'Video',
        Codec: 'hevc',
        Conditions: [
          {
            Condition: 'EqualsAny',
            Property: 'VideoProfile',
            Value: 'main|main 10',
            IsRequired: false,
          },
          {
            Condition: 'LessThanEqual',
            Property: 'VideoLevel',
            Value: '153',
            IsRequired: false,
          },
          {
            Condition: 'EqualsAny',
            Property: 'VideoRangeType',
            Value: videoRanges,
            IsRequired: false,
          },
        ],
      },
      // VP9 + AV1 also support HDR transport; advertise the same range
      // matrix so 4K HDR YouTube-style sources direct-play.
      {
        Type: 'Video',
        Codec: 'vp9',
        Conditions: [
          {
            Condition: 'EqualsAny',
            Property: 'VideoRangeType',
            Value: videoRanges,
            IsRequired: false,
          },
        ],
      },
      {
        Type: 'Video',
        Codec: 'av1',
        Conditions: [
          {
            Condition: 'EqualsAny',
            Property: 'VideoRangeType',
            Value: videoRanges,
            IsRequired: false,
          },
        ],
      },
    ],

    SubtitleProfiles: [
      { Format: 'vtt', Method: 'External' },
      { Format: 'subrip', Method: 'External' },
      { Format: 'ass', Method: 'External' },
      { Format: 'ssa', Method: 'External' },
    ],

    ResponseProfiles: [],
  }
}
