package src

import (
	"cmp"
	"fmt"
	"log"
	"strings"

	"github.com/zoriya/go-mediainfo"
)

// convert mediainfo to RFC 6381, waiting for either of those tickets to be resolved:
//
//	https://sourceforge.net/p/mediainfo/feature-requests/499
//	https://trac.ffmpeg.org/ticket/6617
//
// this code is addapted from https://github.com/jellyfin/jellyfin/blob/master/Jellyfin.Api/Helpers/HlsCodecStringHelpers.cs
func GetMimeCodec(mi *mediainfo.File, kind mediainfo.StreamKind, i int) *string {
	codec := cmp.Or(
		mi.Parameter(kind, i, "InternetMediaType"),
		mi.Parameter(kind, i, "Format"),
	)

	switch codec {
	case "video/H264", "AVC":
		ret := "avc1"
		info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")

		format := info[0]
		switch format {
		case "high":
			ret += ".6400"
		case "main":
			ret += ".4D40"
		case "baseline":
			ret += ".42E0"
		default:
			// Default to constrained baseline if profile is invalid
			ret += ".4240"
		}

		// level format is l3.1 for level 31
		level := ParseFloat(info[1][1:])
		ret += fmt.Sprintf("%02x", int(level*10))
		return &ret

	case "video/H265", "HEVC":
		// The h265 syntax is a bit of a mystery at the time this comment was written.
		// This is what I've found through various sources:
		// FORMAT: [codecTag].[profile].[constraint?].L[level * 30].[UNKNOWN]
		ret := "hvc1"
		info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")

		profile := info[0]
		if profile == "main 10" {
			ret += ".2.4"
		} else {
			ret += ".1.4"
		}

		level := ParseFloat(info[1][:1])
		ret += fmt.Sprintf(".L%02X.BO", int(level*30))
		return &ret

	case "AV1":
		// https://aomedia.org/av1/specification/annex-a/
		// FORMAT: [codecTag].[profile].[level][tier].[bitDepth]
		ret := "av01"
		info := strings.Split(strings.ToLower(mi.Parameter(kind, i, "Format_Profile")), "@")

		profile := info[0]
		switch profile {
		case "main":
			ret += ".0"
		case "high":
			ret += ".1"
		case "professional":
			ret += ".2"
		default:
			// Default to Main
			ret += ".0"
		}

		// level is not defined in mediainfo. using a default
		// Default to the maximum defined level 6.3
		level := 19

		bitdepth := ParseUint(mi.Parameter(kind, i, "BitDepth"))
		if bitdepth != 8 && bitdepth != 10 && bitdepth != 12 {
			// Default to 8 bits
			bitdepth = 8
		}

		tierflag := 'M'
		ret += fmt.Sprintf(".%02X%c.%02d", level, tierflag, bitdepth)

		return &ret

	case "AAC":
		ret := "mp4a"

		profile := strings.ToLower(mi.Parameter(kind, i, "Format_AdditionalFeatures"))
		switch profile {
		case "he":
			ret += ".40.5"
		case "lc":
			ret += ".40.2"
		default:
			ret += ".40.2"
		}

		return &ret

	case "audio/opus", "Opus":
		ret := "Opus"
		return &ret

	case "AC-3":
		ret := "mp4a.a5"
		return &ret

	case "audio/eac3", "E-AC-3":
		ret := "mp4a.a6"
		return &ret

	case "audio/x-flac", "FLAC":
		ret := "fLaC"
		return &ret

	default:
		log.Printf("No known mime format for: %s", codec)
		return nil
	}
}
