package rosa

import (
	"path/filepath"
	"slices"
	"strings"
)

var (
	_cmake = H("cmake")
	_ninja = H("ninja")
)

// CMakeHelper builds and tests a CMake project with specified CACHE entries.
type CMakeHelper struct {
	// Path elements joined with source.
	Append []string

	// Value of CMAKE_BUILD_TYPE. The zero value is equivalent to "Release".
	BuildType string
	// CMake CACHE entries.
	Cache []KV
	// Runs after install.
	Script string

	// Replaces the default test command.
	Test string
	// Whether to skip running tests.
	SkipTest bool

	// Whether to generate Makefile instead.
	Make bool
}

var _ Helper = new(CMakeHelper)

// extra returns the cmake handle alongside either ninja or make.
func (attr *CMakeHelper) extra(int) P {
	if attr != nil && attr.Make {
		return P{_cmake, _make}
	}
	return P{_cmake, _ninja}
}

// wantsChmod returns false.
func (*CMakeHelper) wantsChmod() bool { return false }

// wantsWrite returns false.
func (*CMakeHelper) wantsWrite() bool { return false }

// scriptEarly returns the zero value.
func (*CMakeHelper) scriptEarly() string { return "" }

// wantsDir returns a hardcoded, deterministic pathname.
func (*CMakeHelper) wantsDir() (string, bool) { return "/cure/", true }

// script generates the cure script.
func (attr *CMakeHelper) script(t Toolchain, name string) string {
	if attr == nil {
		attr = new(CMakeHelper)
	}

	generate := "Ninja"
	test := "ninja " + jobsFlagE + " " + loadFlagE + " test"
	if attr.Make {
		generate = "'Unix Makefiles'"
		test = "make " + jobsFlagE + " " + loadFlagE + " test"
	}
	if attr.Test != "" {
		test = attr.Test
	}

	script := attr.Script
	if !attr.SkipTest && t.opts&OptSkipCheck == 0 {
		script += "\n" + test
	}

	cache := make([]KV, 1, 1+len(attr.Cache))
	cache[0] = KV{"CMAKE_BUILD_TYPE", "Release"}
	if attr.BuildType != "" {
		cache[0][1] = attr.BuildType
	}
	cache = append(cache, attr.Cache...)

	return `
cmake -G ` + generate + ` \
	-Wno-author -Wno-unused-cli \
	-DCMAKE_C_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_CXX_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_ASM_COMPILER_TARGET="${ROSA_TRIPLE}" \
	-DCMAKE_INSTALL_LIBDIR=lib \
	` + strings.Join(slices.Collect(func(yield func(string) bool) {
		for _, v := range cache {
			if !yield("-D" + v[0] + "=" + v[1]) {
				return
			}
		}
	}), " \\\n\t") + ` \
	-DCMAKE_INSTALL_PREFIX=/system \
	'/usr/src/` + name + `/` + filepath.Join(attr.Append...) + `'
cmake --build . --parallel=` + jobsE + ` -- ` + loadFlagE + `
DESTDIR=/work cmake --install .
` + script
}
