package rosa

import (
	"slices"

	"hakurei.app/internal/pkg"
)

// newGo returns a specific version of the Go toolchain.
func (t Toolchain) newGo(
	version, checksum string,
	env []string,
	script string,
	boot ...pkg.Artifact,
) pkg.Artifact {
	return t.New("go", version, newTar(
		"https://go.dev/dl/go"+version+".src.tar.gz",
		checksum,
		pkg.Gzip,
	), &PackageAttr{
		EnterSource: true,
		Env: slices.Concat([]string{
			"CC=cc",
			"GOCACHE=/tmp/gocache",
			"GOROOT_BOOTSTRAP=/system/go",
			"TMPDIR=/dev/shm/go",
		}, env),

		Extra: boot,
	}, &GenericHelper{
		InPlace: true,
		Build: `
mkdir /work/system/ "${TMPDIR}"
cp -r . /work/system/go
cd /work/system/go/src/
chmod -R +w ..
` + script + `
set +u
. ./make.bash "$@" --no-banner
set -u
`,
		Check: "bash run.bash --no-rebuild\n",
		Install: `
../bin/go tool dist banner # print build info

mkdir /work/system/bin
ln -s \
	../go/bin/go \
	../go/bin/gofmt \
	/work/system/bin
`,
	},
		_bash,
	)
}

func init() {
	const (
		version  = "1.25.14"
		checksum = "QKYjKzziCmD1eboU__Oi8VjqbPjaHrHAI9ceWyF3D9ORm7cPHN8muZuiGsoLKjCJ"
	)
	meta := Metadata{
		Name:        "go-bootstrap",
		Description: "the Go programming language toolchain (bootstrap)",
		Website:     "https://go.dev",
		Version:     version,
		Exclude:     true,
	}
	native.MustRegister(meta.Name, func(t Toolchain) (*Metadata, pkg.Artifact) {
		var (
			bootstrapEnv   []string
			bootstrapEarly []pkg.Artifact

			finalEnv []string
		)
		switch t.arch {
		case "amd64":
			bootstrapEarly = []pkg.Artifact{t.New("go", "1.4-bootstrap", newTar(
				"https://dl.google.com/go/go1.4-bootstrap-20171003.tar.gz",
				"8o9JL_ToiQKadCTb04nvBDkp8O1xiWOolAxVEqaTGodieNe4lOFEjlOxN3bwwe23",
				pkg.Gzip,
			), &PackageAttr{
				EnterSource: true,
				Env: []string{
					"CGO_ENABLED=0",
				},
			}, &GenericHelper{
				InPlace: true,
				Build: `
mkdir /work/system/
cp -r . /work/system/go
cd /work/system/go/src/
mkdir -p /var/tmp/
./make.bash
`,
			},
				_bash,
			)}

		case "arm64", "riscv64":
			bootstrapEnv = append(bootstrapEnv, "GOROOT_BOOTSTRAP=/system")
			bootstrapEarly = t.Append(bootstrapEarly, H("gcc"))
			finalEnv = append(finalEnv, "CGO_ENABLED=0")

		default:
			panic("unsupported target " + t.arch)
		}

		go119 := t.newGo(
			"1.19",
			"9_e0aFHsIkVxWVGsp9T2RvvjOc3p4n9o9S8tkNe9Cvgzk_zI2FhRQB7ioQkeAAro",
			append(bootstrapEnv, "CGO_ENABLED=0"), `
rm \
	crypto/tls/handshake_client_test.go \
	cmd/pprof/pprof_test.go \
	os/os_unix_test.go
sed -i \
	's/os\.Getenv("GCCGO")$/"nonexistent"/' \
	go/internal/gccgoimporter/importer_test.go
echo \
	'type syscallDescriptor = int' >> \
	os/rawconn_test.go
`, bootstrapEarly...)

		go121 := t.newGo(
			"1.21.13",
			"YtrDka402BOAEwywx03Vz4QlVwoBiguJHzG7PuythMCPHXS8CVMLvzmvgEbu4Tzu",
			[]string{"CGO_ENABLED=0"}, `
sed -i \
	's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
	cmd/link/internal/`+t.arch+`/obj.go

rm \
	crypto/tls/handshake_client_test.go \
	crypto/tls/handshake_server_test.go \
	os/os_unix_test.go
echo \
	'type syscallDescriptor = int' >> \
	os/rawconn_test.go
`, go119,
		)

		go123 := t.newGo(
			"1.23.12",
			"wcI32bl1tkqbgcelGtGWPI4RtlEddd-PTd76Eb-k7nXA5LbE9yTNdIL9QSOOxMOs",
			[]string{"CGO_ENABLED=0"}, `
sed -i \
	's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
	cmd/link/internal/`+t.arch+`/obj.go
`, go121,
		)

		go125 := t.newGo(
			version,
			checksum,
			[]string{"CGO_ENABLED=0"}, `
sed -i \
	's,/lib/ld-musl-`+t.linuxArch()+`.so.1,/system/bin/linker,' \
	cmd/link/internal/`+t.arch+`/obj.go

rm \
	os/root_unix_test.go \
	net/smtp/smtp_test.go
`, go123,
		)

		return &meta, go125
	})
}
