-- Note: loaded scripts will change the current directory due to the code below:
-- https://github.com/premake/premake-core/blob/5b6289407d24fd48d5d8066119295a9c89947c4c/src/host/lua_auxlib.c#L153
-- for this reason we have to change directory manually back at the beginning on each script to avoid major pain!
os.chdir(_MAIN_SCRIPT_DIR)

require("utils")

dependencies = {
	basePath = path.join(_MAIN_SCRIPT_DIR, "thirdparty"),
	depsScriptsPath = path.join(_MAIN_SCRIPT_DIR, "premake/deps"),
}

deps = {} -- actual projects are here

function dependencies.load()
	local dir = path.join(dependencies.depsScriptsPath, "*.lua")
	local deps = os.matchfiles(dir)

	for i, dep in pairs(deps) do
		local dep = dep:gsub(".lua", "")
		require(dep)
	end
end

function dependencies.imports()
	for name, proj in pairs(deps) do
		proj.import()
	end
end

function dependencies.projects()
	for name, proj in pairs(deps) do
		proj.project()
	end
end

dependencies.load()

newoption {
	trigger = "ci-build",
	description = "Enable CI builds."
}

newaction {
	trigger = "generate-buildinfo",
	description = "Sets up build information file like version.h.",
	onWorkspace = function(wks)
		-- get old version number from version.hpp if any
		local oldVersion = "(none)"
		local oldVersionHeader = io.open(wks.location .. "/src/version.h", "r")
		if oldVersionHeader ~= nil then
			local oldVersionHeaderContent = assert(oldVersionHeader:read('*l'))
			while oldVersionHeaderContent do
				m = string.match(oldVersionHeaderContent, "#define GIT_DESCRIBE (.+)%s*$")
				if m ~= nil then
					oldVersion = m
				end

				oldVersionHeaderContent = oldVersionHeader:read('*l')
			end
		end

		-- get current version via git
		local proc = assert(io.popen(gitVersioningCommand, "r"))
		local gitDescribeOutput = assert(proc:read('*a')):gsub("%s+", "")
		proc:close()

		-- generate version.hpp with a revision number if not equal
		gitDescribeOutputQuoted = cstrquote(gitDescribeOutput)
		if oldVersion ~= gitDescribeOutputQuoted then
			-- get current git hash and write to version.txt (used by the preliminary updater)
			local proc = assert(io.popen("git rev-parse HEAD", "r"))
			local gitCommitHash = assert(proc:read('*a')):gsub("%s+", "")
			proc:close()

			-- get whether this is a clean revision (no uncommitted changes)
			proc = assert(io.popen("git status --porcelain", "r"))
			local revDirty = (assert(proc:read('*a')) ~= "")
			if revDirty then revDirty = 1 else revDirty = 0 end
			proc:close()

			-- get current tag name
			proc = assert(io.popen("git describe --tags --abbrev=0"))
			local tagName = proc:read('*l')

			-- patch tag name to be the next one
			if tagName ~= nil and tagName ~= '' and tagName:find("^v%d+$") then
				tagName = string.format("v%u", tagName:sub(tagName:find("%d+$")) + 1)
				print(tagName)
			end

			-- get current branch name
			proc = assert(io.popen("git branch --show-current"))
			local branchName = proc:read('*l')

			-- branch for ci
			if branchName == nil or branchName == '' then
				proc = assert(io.popen("git show -s --pretty=%d HEAD"))
				local branchInfo = proc:read('*l')
				m = branchInfo:match(".+,.+, ([^)]+)")
				if m ~= nil then
					branchName = m
				end
			end

			if branchName == nil then
				branchName = "master"
			end

			print("Detected branch: " .. branchName)

			-- get revision number via git
			local proc = assert(io.popen("git rev-list --count HEAD", "r"))
			local revNumber = assert(proc:read('*a')):gsub("%s+", "")

			print ("Update " .. oldVersion .. " -> " .. gitDescribeOutputQuoted)

			-- write to version.txt for preliminary updater
			-- NOTE - remove this once we have a proper updater and proper release versioning
			local versionFile = assert(io.open(wks.location .. "/version.txt", "w"))
			versionFile:write(gitCommitHash)
			versionFile:close()

			-- write version header
			local versionHeader = assert(io.open(wks.location .. "/src/version.h", "w"))
			versionHeader:write("/*\n")
			versionHeader:write(" * Automatically generated by premake5.\n")
			versionHeader:write(" * Do not touch!\n")
			versionHeader:write(" */\n")
			versionHeader:write("\n")
			versionHeader:write("#define GIT_DESCRIBE " .. gitDescribeOutputQuoted .. "\n")
			versionHeader:write("#define GIT_DIRTY " .. revDirty .. "\n")
			versionHeader:write("#define GIT_HASH " .. cstrquote(gitCommitHash) .. "\n")
			versionHeader:write("#define GIT_TAG " .. cstrquote(tagName) .. "\n")
			versionHeader:write("#define GIT_BRANCH " .. cstrquote(branchName) .. "\n")
			versionHeader:write("\n")
			versionHeader:write("// Version transformed for RC files\n")
			versionHeader:write("#define VERSION_PRODUCT_RC " .. table.concat(vertonumarr(tagName, revNumber, 3), ",") .. "\n")
			versionHeader:write("#define VERSION_PRODUCT " .. cstrquote(table.concat(vertonumarr(tagName, revNumber, 3), ".")) .. "\n")
			versionHeader:write("#define VERSION_FILE_RC " .. table.concat(vertonumarr(tagName, revNumber, 4), ",") .. "\n")
			versionHeader:write("#define VERSION_FILE " .. cstrquote(table.concat(vertonumarr(tagName, revNumber, 4), ".")) .. "\n")
			versionHeader:write("\n")
			versionHeader:write("// Alias definitions\n")
			versionHeader:write("#define VERSION GIT_DESCRIBE\n")
			versionHeader:write("#define SHORTVERSION VERSION_PRODUCT\n")
			versionHeader:close()
			local versionHeader = assert(io.open(wks.location .. "/src/version.hpp", "w"))
			versionHeader:write("/*\n")
			versionHeader:write(" * Automatically generated by premake5.\n")
			versionHeader:write(" * Do not touch!\n")
			versionHeader:write(" *\n")
			versionHeader:write(" * This file exists for reasons of complying with our coding standards.\n")
			versionHeader:write(" *\n")
			versionHeader:write(" * The Resource Compiler will ignore any content from C++ header files if they're not from STDInclude.hpp.\n")
			versionHeader:write(" * That's the reason why we now place all version info in version.h instead.\n")
			versionHeader:write(" */\n")
			versionHeader:write("\n")
			versionHeader:write("#include \"version.h\"\n")
			versionHeader:close()
		end
	end
}

workspace "Fuck_off_EA_App"
startproject "Fuck_off_EA_App"
location "./build"
objdir "%{wks.location}/obj"
targetdir "%{wks.location}/bin/%{cfg.platform}-%{cfg.buildcfg}"
libdirs {"%{wks.location}/bin/%{cfg.platform}-%{cfg.buildcfg}"}

solutionitems {
	"./README.md",
	"./.github/workflows/build.yml",
	["Premake"] = {
		"./premake/*.lua",
		["Deps"] = {
			"./premake/deps/**.lua"
		}
	},
}

configurations {"Release"}

language "C++"
cppdialect "C++20"

architecture "x86"
platforms "Win32"

systemversion "latest"
symbols "On"
staticruntime "On"
editandcontinue "Off"
--warnings "Extra"
characterset "ASCII"

flags {"MultiProcessorCompile", "No64BitChecks"}

defines {"_WINDOWS", "WIN32", "NOMINMAX"}

buildoptions {"/utf-8"}
linkoptions {}

if _OPTIONS["ci-build"] then
	defines {"CI_BUILD"}
end

filter "configurations:Release"
	optimize "Speed"
	buildoptions {}
	linkoptions {}
	defines {"NDEBUG"}
	flags {"LinkTimeOptimization"}
filter {}

filter "configurations:Debug"
	optimize "Debug"
	defines {"DEBUG", "_DEBUG"}
filter {}

includedirs {"./thirdparty"}
libdirs {"./thirdparty"}

require("loader")
require("main")

group "Dependencies"
dependencies.projects()
