/*
    This file is part of jellything (https://codeberg.org/metamuffin/jellything)
    which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
    Copyright (C) 2026 metamuffin <metamuffin.org>
*/
/// <reference lib="dom" />

import { FormatInfo, StreamContainer } from "./types_stream.ts";

const cache = new Map<string, boolean>()

// TODO this testing method makes the assumption, that if the codec is supported on its own, it can be
// TODO     arbitrarly combined with others that are supported. in reality this is true but the spec does not gurantee it.

export async function test_media_capability(format: FormatInfo, container: StreamContainer): Promise<boolean> {
    const cache_key = JSON.stringify(format) + container
    const cached = cache.get(cache_key);
    if (cached !== undefined) return cached
    const r = await test_media_capability_inner(format, container)
    console.log(`${r ? "positive" : "negative"} media capability test finished for codec=${format.codec}`);
    cache.set(cache_key, r)
    return r
}
async function test_media_capability_inner(format: FormatInfo, container: StreamContainer) {
    if (format.codec.startsWith("S_") || format.codec.startsWith("D_")) {
        // TODO do we need to check this?
        return format.codec == "S_TEXT/WEBVTT" || format.codec == "S_TEXT/UTF8" || format.codec == "D_WEBVTT/SUBTITLES"
    }
    let res;
    if (format.codec.startsWith("A_")) {
        res = await navigator.mediaCapabilities.decodingInfo({
            type: "media-source",
            audio: {
                contentType: track_to_content_type(format, container),
                samplerate: format.samplerate,
                channels: "" + format.channels,
                bitrate: format.bitrate,
            }
        })
    }
    if (format.codec.startsWith("V_")) {
        res = await navigator.mediaCapabilities.decodingInfo({
            type: "media-source",
            video: {
                contentType: track_to_content_type(format, container),
                framerate: 30, // TODO get average framerate from server
                width: format.width ?? 1920,
                height: format.height ?? 1080,
                bitrate: format.bitrate
            }
        })
    }
    return res?.supported ?? false
}

export function track_to_content_type(format: FormatInfo, container: StreamContainer): string {
    let c = CONTAINER_TO_MIME_TYPE[container];
    if (format.codec.startsWith("A_")) c = c.replace("video/", "audio/")
    return `${c}; codecs="${MASTROSKA_CODEC_MAP[format.codec]}"`
}

const MASTROSKA_CODEC_MAP: { [key: string]: string } = {
    "V_VP9": "vp9",
    "V_VP8": "vp8",
    "V_AV1": "av1",
    "V_MPEG4/ISO/AVC": "avc1.42C01F",
    "V_MPEGH/ISO/HEVC": "hev1.1.6.L93.90",
    "A_OPUS": "opus",
    "A_VORBIS": "vorbis",
    "S_TEXT/WEBVTT": "webvtt",
    "D_WEBVTT/SUBTITLES": "webvtt",
}
const CONTAINER_TO_MIME_TYPE: { [key in StreamContainer]: string } = {
    webvtt: "text/webvtt",
    webm: "video/webm",
    matroska: "video/x-matroska",
    mpeg4: "video/mp4",
    jvtt: "application/jellything-vtt+json"
}
