package main

import (
	"flag"
	"strings"

	_ "embed"

	logger "git.site.quack-lab.dev/dave/cylogger"
	utils "git.site.quack-lab.dev/dave/cyutils"
)

func main() {
	outdir := flag.String("o", ".", "Output directory")
	flag.Parse()
	logger.InitFlag()
	logger.Info("Starting...")

	files := flag.Args()
	if len(files) == 0 {
		logger.Error("No files specified")
		flag.Usage()
		return
	}

	// TODO: Implement parsing enums somehow
	// TODO: Implement some sort of switching (between a class and an enum)
	utils.WithWorkers(10, files, func(worker int, file string) {
		class, err := ParseClass(file)
		if err != nil {
			logger.Error("Error parsing file: %v", err)
			return
		}
		class.Write(*outdir, classTemplate)
	})
}

func MapType(t string) string {
	// Handle complex types like table<int, string>
	if strings.Contains(t, "<") && strings.Contains(t, ">") {
		// Extract the base type and inner types
		openBracket := strings.Index(t, "<")
		closeBracket := strings.LastIndex(t, ">")
		if openBracket != -1 && closeBracket != -1 {
			baseType := t[:openBracket]
			innerTypes := t[openBracket+1 : closeBracket]

			// Split inner types by comma, but be careful about nested brackets
			var mappedInnerTypes []string
			var current strings.Builder
			bracketDepth := 0

			for i := 0; i < len(innerTypes); i++ {
				char := innerTypes[i]
				if char == '<' {
					bracketDepth++
					current.WriteByte(char)
				} else if char == '>' {
					bracketDepth--
					current.WriteByte(char)
				} else if char == ',' && bracketDepth == 0 {
					// Only split on commas that are not inside nested brackets
					mappedInnerTypes = append(mappedInnerTypes, MapType(strings.TrimSpace(current.String())))
					current.Reset()
				} else {
					current.WriteByte(char)
				}
			}
			// Add the last inner type
			if current.Len() > 0 {
				mappedInnerTypes = append(mappedInnerTypes, MapType(strings.TrimSpace(current.String())))
			}

			// Reconstruct the complex type
			return baseType + "<" + strings.Join(mappedInnerTypes, ", ") + ">"
		}
	}

	// Handle simple types
	switch t {
	case "var":
		return "any"
	case "var...":
		return "..."
	case "int":
		return "number"
	case "int...":
		return "number..."
	case "unsigned int":
		return "number"
	case "float":
		return "number"
	case "double":
		return "number"
	case "bool":
		return "boolean"
	case "char":
		return "string"
	case "table_t":
		return "table"
	default:
		return t
	}
}

func IsReservedKeyword(t string) bool {
	switch t {
	case "and", "break", "do", "else", "elseif", "end", "false", "for", "function", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "any", "boolean", "number", "string", "table", "thread", "userdata", "var":
		return true
	}
	return false
}
