package rosa

import (
	"slices"
	"strings"

	"hakurei.app/internal/pkg"
)

func (t Toolchain) newSPIRVHeaders() (pkg.Artifact, string) {
	const (
		version  = "1.4.341.0"
		checksum = "0PL43-19Iaw4k7_D8J8BvoJ-iLgCVSYZ2ThgDPGfAJwIJFtre7l0cnQtLjcY-JvD"
	)
	return t.NewPackage("spirv-headers", version, newFromGitHub(
		"KhronosGroup/SPIRV-Headers",
		"vulkan-sdk-"+version,
		checksum,
	), nil, &CMakeHelper{
		// upstream has no tests
		SkipTest: true,
	}), version
}
func init() {
	artifactsM[SPIRVHeaders] = Metadata{
		f: Toolchain.newSPIRVHeaders,

		Name:        "spirv-headers",
		Description: "machine-readable files for the SPIR-V Registry",
		Website:     "https://github.com/KhronosGroup/SPIRV-Headers",

		ID: 230542,

		// upstream changed version scheme, anitya incapable of filtering them
		latest: func(v *Versions) string {
			for _, s := range v.Stable {
				fields := strings.SplitN(s, ".", 4)
				if len(fields) != 4 {
					continue
				}
				if slices.ContainsFunc(fields, func(f string) bool {
					return slices.ContainsFunc([]byte(f), func(d byte) bool {
						return d < '0' || d > '9'
					})
				}) {
					continue
				}
				return s
			}
			return v.Latest
		},
	}
}

func (t Toolchain) newSPIRVTools() (pkg.Artifact, string) {
	const (
		version  = "2026.1"
		checksum = "ZSQPQx8NltCDzQLk4qlaVxyWRWeI_JtsjEpeFt3kezTanl9DTHfLixSUCezMFBjv"
	)
	return t.NewPackage("spirv-tools", version, newFromGitHub(
		"KhronosGroup/SPIRV-Tools",
		"v"+version,
		checksum,
	), nil, &CMakeHelper{
		Cache: []KV{
			{"SPIRV-Headers_SOURCE_DIR", "/system"},
		},
	},
		Python,

		SPIRVHeaders,
	), version
}
func init() {
	artifactsM[SPIRVTools] = Metadata{
		f: Toolchain.newSPIRVTools,

		Name:        "spirv-tools",
		Description: "an API and commands for processing SPIR-V modules",
		Website:     "https://github.com/KhronosGroup/SPIRV-Tools",

		Dependencies: P{
			SPIRVHeaders,
		},

		ID: 14894,

		latest: (*Versions).getStable,
	}
}

func (t Toolchain) newGlslang() (pkg.Artifact, string) {
	const (
		version  = "16.3.0"
		checksum = "xyqDf8k3-D0_BXHGi0uLgMglnJ05Rf3j73QgbDs3sGtKNdBIQhY8JfqX1NcNoJQN"
	)
	return t.NewPackage("glslang", version, newFromGitHub(
		"KhronosGroup/glslang",
		version,
		checksum,
	), &PackageAttr{
		// test suite writes to source
		Writable: true,
		Chmod:    true,
	}, &CMakeHelper{
		Cache: []KV{
			{"BUILD_SHARED_LIBS", "ON"},
			{"ALLOW_EXTERNAL_SPIRV_TOOLS", "ON"},
		},
	},
		Python,
		Bash,
		Diffutils,

		SPIRVTools,
	), version
}
func init() {
	artifactsM[Glslang] = Metadata{
		f: Toolchain.newGlslang,

		Name:        "glslang",
		Description: "reference front end for GLSL/ESSL",
		Website:     "https://github.com/KhronosGroup/glslang",

		ID: 205796,
	}
}

func (t Toolchain) newSPIRVLLVMTranslator() (pkg.Artifact, string) {
	const (
		version  = "22.1.2"
		checksum = "JZAaV5ewYcm-35YA_U2BM2IcsQouZtX1BLZR0zh2vSlfEXMsT5OCtY4Gh5RJkcGy"
	)
	skipChecks := []string{
		// error: line 13: OpTypeCooperativeMatrixKHR Scope is limited to Workgroup and Subgroup
		"cooperative_matrix_constant_null.spvasm",
	}

	switch arch {
	case "arm64":
		skipChecks = append(skipChecks,
			// LLVM ERROR: unsupported calling convention
			"DebugInfo/COFF/no-cus.ll",
			"DebugInfo/Generic/2009-11-05-DeadGlobalVariable.ll",
			"DebugInfo/Generic/2009-11-10-CurrentFn.ll",
			"DebugInfo/Generic/2010-01-05-DbgScope.ll",
			"DebugInfo/Generic/2010-03-12-llc-crash.ll",
			"DebugInfo/Generic/2010-03-24-MemberFn.ll",
			"DebugInfo/Generic/2010-04-19-FramePtr.ll",
			"DebugInfo/Generic/2010-06-29-InlinedFnLocalVar.ll",
			"DebugInfo/Generic/2010-10-01-crash.ll",
			"DebugInfo/Generic/PR20038.ll",
			"DebugInfo/Generic/constant-pointers.ll",
			"DebugInfo/Generic/dead-argument-order.ll",
			"DebugInfo/Generic/debug-info-eis-option.ll",
			"DebugInfo/Generic/def-line.ll",
			"DebugInfo/Generic/discriminator.ll",
			"DebugInfo/Generic/dwarf-public-names.ll",
			"DebugInfo/Generic/enum.ll",
			"DebugInfo/Generic/func-using-decl.ll",
			"DebugInfo/Generic/global.ll",
			"DebugInfo/Generic/imported-name-inlined.ll",
			"DebugInfo/Generic/incorrect-variable-debugloc1.ll",
			"DebugInfo/Generic/inline-scopes.ll",
			"DebugInfo/Generic/inlined-arguments.ll",
			"DebugInfo/Generic/inlined-vars.ll",
			"DebugInfo/Generic/linear-dbg-value.ll",
			"DebugInfo/Generic/linkage-name-abstract.ll",
			"DebugInfo/Generic/member-order.ll",
			"DebugInfo/Generic/missing-abstract-variable.ll",
			"DebugInfo/Generic/multiline.ll",
			"DebugInfo/Generic/namespace_function_definition.ll",
			"DebugInfo/Generic/namespace_inline_function_definition.ll",
			"DebugInfo/Generic/noscopes.ll",
			"DebugInfo/Generic/ptrsize.ll",
			"DebugInfo/Generic/restrict.ll",
			"DebugInfo/Generic/two-cus-from-same-file.ll",
			"DebugInfo/Generic/version.ll",
			"DebugInfo/LocalAddressSpace.ll",
			"DebugInfo/UnknownBaseType.ll",
			"DebugInfo/expr-opcode.ll",
		)
	}

	return t.NewPackage("spirv-llvm-translator", version, newFromGitHub(
		"KhronosGroup/SPIRV-LLVM-Translator",
		"v"+version, checksum,
	), &PackageAttr{
		Patches: []KV{
			{"remove-early-prefix", `diff --git a/CMakeLists.txt b/CMakeLists.txt
index c000a77e..f18f3fde 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -164,7 +164,7 @@ install(
     ${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVOpts.h
     ${LLVM_SPIRV_INCLUDE_DIRS}/LLVMSPIRVExtensions.inc
   DESTINATION
-    ${CMAKE_INSTALL_PREFIX}/include/LLVMSPIRVLib
+    include/LLVMSPIRVLib
 )
 
 configure_file(LLVMSPIRVLib.pc.in ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc @ONLY)
@@ -172,5 +172,5 @@ install(
   FILES
     ${CMAKE_BINARY_DIR}/LLVMSPIRVLib.pc
   DESTINATION
-    ${CMAKE_INSTALL_PREFIX}/lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
+    lib${LLVM_LIBDIR_SUFFIX}/pkgconfig
 )
;`},
		},

		// litArgs emits shell syntax
		ScriptEarly: `
export LIT_OPTS=` + litArgs(true, skipChecks...) + `
`,
	}, &CMakeHelper{
		Cache: []KV{
			{"CMAKE_SKIP_BUILD_RPATH", "ON"},
			{"BUILD_SHARED_LIBS", "ON"},
			{"LLVM_SPIRV_ENABLE_LIBSPIRV_DIS", "ON"},
			{"LLVM_EXTERNAL_SPIRV_HEADERS_SOURCE_DIR", "/system"},
			{"LLVM_EXTERNAL_LIT", "/system/bin/lit"},
			{"LLVM_INCLUDE_TESTS", "ON"},
		},
	},
		Bash,
		LIT,

		SPIRVTools,
	), version
}
func init() {
	artifactsM[SPIRVLLVMTranslator] = Metadata{
		f: Toolchain.newSPIRVLLVMTranslator,

		Name:        "spirv-llvm-translator",
		Description: "bi-directional translation between SPIR-V and LLVM IR",
		Website:     "https://github.com/KhronosGroup/SPIRV-LLVM-Translator",

		Dependencies: P{
			SPIRVTools,
		},

		ID: 227273,
	}
}
