package meta

import "core:fmt"
import "core:log"
import "core:mem"
import "core:os"

Command :: struct {
	name:        string,
	description: string,
	run:         proc() -> bool,
}

COMMANDS :: []Command {
	{
		name = "gen-shaders",
		description = "Compile GLSL shaders to SPIR-V and Metal Shading Language.",
		run = proc() -> bool {
			return gen_shaders("draw/shaders/source", "draw/shaders/generated")
		},
	},
}

main :: proc() {
	//----- General setup ----------------------------------
	when ODIN_DEBUG {
		// Temp
		track_temp: mem.Tracking_Allocator
		mem.tracking_allocator_init(&track_temp, context.temp_allocator)
		context.temp_allocator = mem.tracking_allocator(&track_temp)

		// Default
		track: mem.Tracking_Allocator
		mem.tracking_allocator_init(&track, context.allocator)
		context.allocator = mem.tracking_allocator(&track)
		// Log a warning about any memory that was not freed by the end of the program.
		// This could be fine for some global state or it could be a memory leak.
		defer {
			// Temp allocator
			if len(track_temp.bad_free_array) > 0 {
				fmt.eprintf("=== %v incorrect frees - temp allocator: ===\n", len(track_temp.bad_free_array))
				for entry in track_temp.bad_free_array {
					fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
				}
				mem.tracking_allocator_destroy(&track_temp)
			}
			// Default allocator
			if len(track.allocation_map) > 0 {
				fmt.eprintf("=== %v allocations not freed - main allocator: ===\n", len(track.allocation_map))
				for _, entry in track.allocation_map {
					fmt.eprintf("- %v bytes @ %v\n", entry.size, entry.location)
				}
			}
			if len(track.bad_free_array) > 0 {
				fmt.eprintf("=== %v incorrect frees - main allocator: ===\n", len(track.bad_free_array))
				for entry in track.bad_free_array {
					fmt.eprintf("- %p @ %v\n", entry.memory, entry.location)
				}
			}
			mem.tracking_allocator_destroy(&track)
		}
		// Logger
		context.logger = log.create_console_logger()
		defer log.destroy_console_logger(context.logger)
	}

	args := os.args[1:]

	if len(args) == 0 {
		print_usage()
		return
	}

	command_name := args[0]
	for command in COMMANDS {
		if command.name == command_name {
			if !command.run() do os.exit(1)
			return
		}
	}

	fmt.eprintfln("Unknown command '%s'.", command_name)
	fmt.eprintln()
	print_usage()
	os.exit(1)
}

print_usage :: proc() {
	fmt.eprintln("Usage: meta <command>")
	fmt.eprintln()
	fmt.eprintln("Commands:")
	for command in COMMANDS {
		fmt.eprintfln("  %-20s %s", command.name, command.description)
	}
}
