//go:build ignore

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"os"
	"sort"
	"strings"
	"text/template"
)

const outputTemplate = `// Code generated by gen/main.go; DO NOT EDIT.

package opcodes

// initializeNameMappings populates nameToEmu from constants
func (om *OpcodeManager) initializeNameMappings() {
{{- range . }}
	om.nameToEmu["{{ .Name }}"] = {{ .Name }}
{{- end }}
}
`

type OpcodeInfo struct {
	Name string
}

func main() {
	opcodes := []OpcodeInfo{}

	// Parse each source file for OP_ constants
	files := []string{"login.go", "emu.go"}

	for _, filename := range files {
		fset := token.NewFileSet()
		node, err := parser.ParseFile(fset, filename, nil, parser.ParseComments)
		if err != nil {
			fmt.Fprintf(os.Stderr, "Failed to parse %s: %v\n", filename, err)
			continue
		}

		// Find all OP_ and LS_ constants
		ast.Inspect(node, func(n ast.Node) bool {
			spec, ok := n.(*ast.ValueSpec)
			if !ok {
				return true
			}

			for _, name := range spec.Names {
				if strings.HasPrefix(name.Name, "OP_") || strings.HasPrefix(name.Name, "LS_") {
					opcodes = append(opcodes, OpcodeInfo{Name: name.Name})
				}
			}
			return true
		})
	}

	// Sort for consistent output
	sort.Slice(opcodes, func(i, j int) bool {
		return opcodes[i].Name < opcodes[j].Name
	})

	// Generate output
	tmpl, err := template.New("opcodes").Parse(outputTemplate)
	if err != nil {
		panic(err)
	}

	file, err := os.Create("generated.go")
	if err != nil {
		panic(err)
	}
	defer file.Close()

	if err := tmpl.Execute(file, opcodes); err != nil {
		panic(err)
	}

	fmt.Printf("Generated %d opcode mappings\n", len(opcodes))
}
