// miqt-rcc compiles a Qt resource XML file (*.qrc) to a binary resource file and
// creates a Go stub to load it.
package main

import (
	"flag"
	"fmt"
	"go/format"
	"io/ioutil"
	"os"
	"os/exec"
	"path/filepath"
	"strconv"
	"strings"
)

const (
	DefaultPackageName  string = "main"
	DefaultVariableName string = "_resourceRcc"
	DefaultIsQt6        bool   = false
	DefaultRccBinary    string = "rcc"
)

func RccExec() error {

	// Parse arguments

	input := flag.String("Input", "", "Path to .qrc input file")
	outputGo := flag.String("OutputGo", "", "(Optional) Path to .go output file. If omitted, interred from the input file path")
	outputRcc := flag.String("OutputRcc", "", "(Optional) Path to .rcc output file. If omitted, inferred from the output Go file path")
	packageName := flag.String("Package", DefaultPackageName, "Package to use in generated Go files")
	variableName := flag.String("VariableName", DefaultVariableName, "Temporary global variable name for loading embedded data")
	useQt6 := flag.Bool("Qt6", DefaultIsQt6, "Use Qt 6 instead of Qt 5")
	rccBinary := flag.String("RccBinary", DefaultRccBinary, "(Optional) Custom path to the Qt rcc program")
	flag.Parse()

	// Check if input file exists

	if _, err := os.Stat(*input); os.IsNotExist(err) {
		return fmt.Errorf("Input file '%s' not found\n", *input)
	}

	// Fill in default output names, if not specified

	if *outputGo == "" {
		*outputGo = strings.TrimSuffix(*input, `.qrc`) + `.go`
	}
	if *outputRcc == "" {
		// Base this on the outputGo filename, not the input filename
		*outputRcc = strings.TrimSuffix(*outputGo, `.go`) + `.rcc`
	}

	// The rcc output path must be relative to the output go file path

	embedPath, err := filepath.Rel(filepath.Dir(*outputGo), *outputRcc)
	if err != nil {
		return err
	}

	// Compile qrc to binary resource file

	rccCmd := exec.Command(*rccBinary, `--binary`, `-o`, *outputRcc, *input)
	rccCmd.Stderr = os.Stderr
	rccCmd.Stdout = os.Stdout
	err = rccCmd.Run()
	if err != nil {
		return err
	}

	// Figure out import statement

	miqtImport := `"github.com/mappu/miqt/qt"`
	if *useQt6 {
		miqtImport = `qt "github.com/mappu/miqt/qt6"`
	}

	// Figure out regeneration command

	generate := `miqt-rcc` +
		` -Input ` + strconv.Quote(*input) +
		` -OutputGo ` + strconv.Quote(filepath.Base(*outputGo)) +
		` -OutputRcc ` + strconv.Quote(embedPath)
	if *packageName != DefaultPackageName {
		generate += ` -Package ` + strconv.Quote(*packageName)
	}
	if *variableName != DefaultVariableName {
		generate += ` -Variable ` + strconv.Quote(*variableName)
	}
	if *useQt6 != DefaultIsQt6 {
		generate += ` -Qt6`
	}
	if *rccBinary != DefaultRccBinary {
		generate += ` -RccBinary ` + strconv.Quote(*rccBinary)
	}

	// Create Go file that loads the resource

	goSrcData := `
package ` + *packageName + `

//go:generate ` + generate + `

import (
	"embed"
	
	` + miqtImport + `
)

//go:embed ` + embedPath + `
var ` + *variableName + ` []byte

func init() {
	_ = embed.FS{}
	qt.QResource_RegisterResourceWithRccData(& ` + *variableName + `[0])
}

`

	outputData, err := format.Source([]byte(goSrcData))
	if err != nil {
		return err
	}

	err = ioutil.WriteFile(*outputGo, outputData, 0644)
	if err != nil {
		return fmt.Errorf("Writing to '%s': %w", *outputGo, err)
	}

	return nil
}

func main() {
	err := RccExec()
	if err != nil {
		fmt.Fprintf(os.Stderr, "rcc: %s\n", err.Error())
		os.Exit(1)
	}

	fmt.Println("RCC OK")
	os.Exit(0)
}