//go:build darwin && cgo

package platform

/*
#cgo CFLAGS: -x objective-c
#cgo LDFLAGS: -framework VideoToolbox -framework CoreMedia -framework CoreFoundation

#import <VideoToolbox/VideoToolbox.h>

int checkHardwareSupport(OSType codecType) {
    return (int)VTIsHardwareDecodeSupported(codecType);
}
*/
import "C"
import (
	"encoding/binary"
	"fmt"
	"gitgud.io/mike/mpv-manager/pkg/log"
)

type codecFourCC struct {
	fourCC uint32
	name   string
}

var darwinCodecs = []codecFourCC{
	{makeFourCC('a', 'v', '0', '1'), "av1"},    // 'av01' (AV1) - kCMVideoCodecType_AV1
	{makeFourCC('v', 'p', '0', '9'), "vp9"},    // 'vp09' (VP9) - kCMVideoCodecType_VP9
	{makeFourCC('h', 'v', 'c', '1'), "hevc"},   // 'hvc1' (H.265/HEVC) - kCMVideoCodecType_HEVC
	{makeFourCC('a', 'p', 'c', 'n'), "prores"}, // 'apcn' (ProRes 422) - kCMVideoCodecType_ProRes422
	{makeFourCC('a', 'v', 'c', '1'), "avc"},    // 'avc1' (H.264/AVC) - kCMVideoCodecType_H264
}

func makeFourCC(a, b, c, d byte) uint32 {
	return binary.BigEndian.Uint32([]byte{a, b, c, d})
}

func detectCodecSupportDarwin() ([]string, error) {
	log.Info("Using CGO detection for accurate hardware decoder support")
	return detectCodecSupportDarwinCGO()
}

func detectCodecSupportDarwinCGO() ([]string, error) {
	var detected []string

	for _, codec := range darwinCodecs {
		supported := C.checkHardwareSupport(C.OSType(codec.fourCC))
		if supported != 0 {
			detected = append(detected, codec.name)
		}
	}

	if len(detected) == 0 {
		return nil, fmt.Errorf("no hardware decoder support detected")
	}

	return detected, nil
}
