package main

import (
	"flag"
	"fmt"
	"os"
	"strings"
	"time"
)

func main() {
	// Define flags for all configurable parameters.
	name := flag.String("name", "", "Application name (e.g. 'Spitfire Installer')")
	version := flag.String("version", "", "Application version (e.g. '2025.02.11.0'). If empty, current date will be used")
	company := flag.String("company", "", "Company name")
	description := flag.String("description", "", "File description")
	internalName := flag.String("internalName", "", "Internal name for the application (default: same as name)")
	officialURL := flag.String("official", "", "Official website URL")
	devURL := flag.String("dev", "", "Source/Development website URL")
	requireAdmin := flag.Bool("requireAdmin", false, "Set to true if the application requires administrator privileges")

	flag.Parse()

	// Validate required parameters.
	if *name == "" || *company == "" || *description == "" || *officialURL == "" || *devURL == "" {
		fmt.Println("Error: --name, --company, --description, --official, and --dev are required")
		flag.Usage()
		os.Exit(1)
	}

	// Use name as default for internalName if not provided.
	if *internalName == "" {
		*internalName = *name
	}

	// Use current date as version if not provided.
	if *version == "" {
		now := time.Now().Format("2006.01.02")
		*version = now + ".0"
	}

	// --- Generate app.manifest ---
	level := "asInvoker"
	if *requireAdmin {
		level = "requireAdministrator"
	}

	manifestContent := fmt.Sprintf(`<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel level="%s" uiAccess="false"/>
            </requestedPrivileges>
        </security>
    </trustInfo>
</assembly>
`, level)

	if err := os.WriteFile("app.manifest", []byte(manifestContent), 0644); err != nil {
		fmt.Println("Error writing app.manifest:", err)
		os.Exit(1)
	}

	// --- Generate app.rc (Resource Script) ---
	// Convert version string "YYYY.MM.DD.0" into numeric version parts.
	parts := strings.Split(*version, ".")
	if len(parts) < 4 {
		fmt.Println("Version must have at least 4 parts separated by '.'")
		os.Exit(1)
	}
	// Remove leading zeros.
	v1 := strings.TrimLeft(parts[0], "0")
	if v1 == "" {
		v1 = "0"
	}
	v2 := strings.TrimLeft(parts[1], "0")
	if v2 == "" {
		v2 = "0"
	}
	v3 := strings.TrimLeft(parts[2], "0")
	if v3 == "" {
		v3 = "0"
	}
	v4 := strings.TrimLeft(parts[3], "0")
	if v4 == "" {
		v4 = "0"
	}
	fileVersion := fmt.Sprintf("%s,%s,%s,%s", v1, v2, v3, v4)

	// Generate the resource script.
	// Note: The manifest is embedded here under resource ID 1 (type 24), but after running, it's enforced by mt.exe. 
	// I'm not sure if I should remove mt.exe enforcement or remove it here.
	rcContent := fmt.Sprintf(`1 VERSIONINFO
FILEVERSION     %s
PRODUCTVERSION  %s
FILEFLAGSMASK   0x3fL
#ifdef _DEBUG
FILEFLAGS       0x1L
#else
FILEFLAGS       0x0L
#endif
FILEOS          0x40004L
FILETYPE        0x1L
FILESUBTYPE     0x0L
BEGIN
    BLOCK "StringFileInfo"
    BEGIN
        BLOCK "040904E4"
        BEGIN
            VALUE "CompanyName", "%s\0"
            VALUE "FileDescription", "%s\0"
            VALUE "FileVersion", "%s\0"
            VALUE "InternalName", "%s\0"
            VALUE "OriginalFilename", "%s.exe\0"
            VALUE "ProductName", "%s\0"
            VALUE "ProductVersion", "%s\0"
            VALUE "Comments", "Official website: %s; Source/Dev website: %s\0"
        END
    END
    BLOCK "VarFileInfo"
    BEGIN
        VALUE "Translation", 0x0409, 1252
    END
END

1 24 "app.manifest"
`, fileVersion, fileVersion, *company, *description, *version, *internalName, *internalName, *name, *version, *officialURL, *devURL)

	if err := os.WriteFile("app.rc", []byte(rcContent), 0644); err != nil {
		fmt.Println("Error writing app.rc:", err)
		os.Exit(1)
	}

	fmt.Printf("Generated app.manifest and app.rc with version: %s\n", *version)
}