package main

import (
	"flag"
	"fmt"
	"os"
	"os/exec"
)

var envtype int // set by user with cli flag

const (
	ENVIRONMENT_DEV        = iota
	ENVIRONMENT_STAGING    = iota
	ENVIRONMENT_PRODUCTION = iota
)

const METAGEN_AUTO_COMMENT = "// @Metagen -- THIS FILE WAS AUTOGENERATED OR PREPROCESSED BY METAGEN - DO NOT EDIT BY HAND"

// metagen - code generator application
//
// Generates code for other applications, such as the server application
func main() {
	env := flag.String("env", "dev", "The environment to run in: dev, staging, or production")

	// Parse command-line flags
	flag.Parse()

	switch *env {
	case "dev":
		envtype = ENVIRONMENT_DEV
	case "staging":
		envtype = ENVIRONMENT_STAGING
	case "production":
		envtype = ENVIRONMENT_PRODUCTION
	default:
		fmt.Printf("Invalid environment specified: %s\n", *env)
		fmt.Println("Allowed values are: dev, staging, or production")
		os.Exit(1)
	}

	args := flag.Args()

	for _, arg := range args {
		switch arg {
		case "build-all":
			preBuild()
			build()
			goto End
		case "build":
			preBuild()
			goto End
		case "migrate":
			migrations(args)
			goto End
		default:
			helpmsg()
			goto End
		}
	}

End:

	if len(args) == 0 {
		helpmsg()
	}
}

func helpmsg() {
	fmt.Println("Usage: metagen [options...]")
	fmt.Println("build :: Build dependencies, generate code, then build final executables.")
	fmt.Println("migrate [up, down, goto {V}, create {migration name}] :: Deploy and create SQL migrations.")
	os.Exit(1)
}

func preBuild() {
	if envtype == ENVIRONMENT_DEV {
		fmt.Println("[DEBUG ENVIRONMENT]")
	} else if envtype == ENVIRONMENT_STAGING || envtype == ENVIRONMENT_PRODUCTION {
		fmt.Println("[RELEASE ENVIRONMENT]")
	}

	// db creation
	maybeCreateSqliteDb()

	// code generation
	generateInlineStyles()
	generateDebugConfig()
	generateJetModels()
}

func build() {
	compileServer()
}

func compileServer() {
	var out []byte
	var err error

	fmt.Printf("Compiling Server Binary")

	if envtype == ENVIRONMENT_DEV {
		// include extra flags for the GC
		out, err = exec.Command("go", "build", "-gcflags=all=-N -l", "./cmd/server").CombinedOutput()
	} else {
		out, err = exec.Command("go", "build", "./cmd/server").CombinedOutput()
	}

	handleCmdOutput(out, err)
	printStatus(true)
}
