-- Generates a FASTBuild config file for a solution.

-- Note that table order iteration should be deterministic, so the .bff file content is not
-- arbitrarily changed each time it's generated. There are several places in this file
-- where sorts are done for that reason.

	function premake.fastbuild.solution(sln)
		-- Presuppose we are building a fastbuild config for vs2015 only.

		io.indent = '    '
		_p('// FastBuild solution configuration file.  Generated by GENie.')
		_p('//------------------------------------------------------------------------------------')
		_p('// %s', sln.name)
		_p('//------------------------------------------------------------------------------------')

		_p('#import VS140COMNTOOLS')

		-- Create a batch file to run vcvarsall, and capture the variables it sets:
		local is64bit = os.is64bit()
		local target64 = (is64bit and ' amd64') or ' x86_amd64'
		local target32 = (is64bit and ' amd64_x86') or ''

		local getvcvarscontent = [[
@set INCLUDE=
@set LIB=
@set CommandPromptType=
@set PreferredToolArchitecture=
@set Platform=
@set Path=%SystemRoot%\System32;%SystemRoot%;%SystemRoot%\System32\wbem

@call "%VS140COMNTOOLS%..\..\VC\vcvarsall.bat" %1

@echo %INCLUDE%
@echo %LIB%
@echo %CommandPromptType%
@echo %PreferredToolArchitecture%
@echo %Platform%
@echo %Path%
]]

		-- Save the temp file.

		local getvcvarsfilepath = os.getenv('TEMP')..'\\getvcvars.bat'

		local getvcvarsfile = assert(io.open(getvcvarsfilepath, 'w'))
		getvcvarsfile:write(getvcvarscontent)
		getvcvarsfile:close()

		local vcvarsrawx86 = os.outputof(string.format('call "%s"%s', getvcvarsfilepath, target32))
		local vcvarsrawx64 = os.outputof(string.format('call "%s"%s', getvcvarsfilepath, target64))

		os.remove(getvcvarsfilepath)

		local msvcvars = {}
		msvcvars.x32 = {}
		msvcvars.x64 = {}

		local includeslibssplitter = string.gmatch(vcvarsrawx64, "[^\n]+")
		msvcvars.x64.includesraw = includeslibssplitter()
		msvcvars.x64.libpathsraw = includeslibssplitter()
		msvcvars.x64.commandprompttype = includeslibssplitter()
		msvcvars.x64.preferredtoolarchitecture = includeslibssplitter()
		msvcvars.x64.platform = includeslibssplitter()
		msvcvars.x64.pathraw = includeslibssplitter()

		includeslibssplitter = string.gmatch(vcvarsrawx86, "[^\n]+")
		msvcvars.x32.includesraw = includeslibssplitter()
		msvcvars.x32.libpathsraw = includeslibssplitter()
		msvcvars.x32.commandprompttype = includeslibssplitter()
		msvcvars.x32.preferredtoolarchitecture = includeslibssplitter()
		msvcvars.x32.platform = includeslibssplitter()
		msvcvars.x32.pathraw = includeslibssplitter()

		local function printincludes(includesraw)
			_p(1, ".MSVCIncludes = ''")
			for i in string.gmatch(includesraw, "[^;]+") do
				_p(2, "+ ' /I\"%s\"'", i)
			end
		end

		local function printlibpaths(libpathsraw)
			_p(1, ".MSVCLibPaths = ''")
			for i in string.gmatch(libpathsraw, "[^;]+") do
				_p(2, "+ ' /LIBPATH:\"%s\"'", i)
			end
		end

		if is64bit then
			_p('.MSVCx64Config =')
			_p('[')
			_p(1, ".Compiler  = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64\\cl.exe'")
			_p(1, ".Librarian = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64\\lib.exe'")
			_p(1, ".Linker    = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64\\link.exe'")
			printincludes(msvcvars.x64.includesraw)
			printlibpaths(msvcvars.x64.libpathsraw)
			_p(']')
			_p('')

			_p('.MSVCx86Config =')
			_p('[')
			_p(1, ".Compiler  = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64_x86\\cl.exe'")
			_p(1, ".Librarian = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64_x86\\lib.exe'")
			_p(1, ".Linker    = '$VS140COMNTOOLS$..\\..\\VC\\bin\\amd64_x86\\link.exe'")
			printincludes(msvcvars.x32.includesraw)
			printlibpaths(msvcvars.x32.libpathsraw)
			_p(']')
			_p('')
		else
			_p('.MSVCx64Config =')
			_p('[')
			_p(1, ".Compiler  = '$VS140COMNTOOLS$..\\..\\VC\\bin\\x86_amd64\\cl.exe'")
			_p(1, ".Librarian = '$VS140COMNTOOLS$..\\..\\VC\\bin\\x86_amd64\\lib.exe'")
			_p(1, ".Linker    = '$VS140COMNTOOLS$..\\..\\VC\\bin\\x86_amd64\\link.exe'")
			printincludes(msvcvars.x64.includesraw)
			printlibpaths(msvcvars.x64.libpathsraw)
			_p(']')
			_p('')

			_p('.MSVCx86Config =')
			_p('[')
			_p(1, ".Compiler  = '$VS140COMNTOOLS$..\\..\\VC\\bin\\cl.exe'")
			_p(1, ".Librarian = '$VS140COMNTOOLS$..\\..\\VC\\bin\\lib.exe'")
			_p(1, ".Linker    = '$VS140COMNTOOLS$..\\..\\VC\\bin\\link.exe'")
			printincludes(msvcvars.x32.includesraw)
			printlibpaths(msvcvars.x32.libpathsraw)
			_p(']')
			_p('')
		end

		local msvcbin = '$VS140COMNTOOLS$..\\..\\VC\\bin' .. ((is64bit and '\\amd64') or '')
		_p('#import Path')
		_p('#import TMP')
		_p('#import SystemRoot')
		_p('')
		_p('Settings')
		_p('{')
		_p(1, '.Environment = {')
		_p(2, "'Path=%s;$Path$',", msvcbin)
		_p(2, "'TMP=$TMP$',")
		_p(2, "'SystemRoot=$SystemRoot$',")
		_p(2, '}')
		_p('}')
		_p('')

		local function projkindsort(a, b)
			local projvaluemap = {
				ConsoleApp  = 3,
				WindowedApp = 3,
				SharedLib   = 2,
				StaticLib   = 1,
			}

			if projvaluemap[a.kind] == projvaluemap[b.kind] then
				return a.name < b.name
			else
				return projvaluemap[a.kind] < projvaluemap[b.kind]
			end
		end

		local sortedprojs = {}
		for prj in premake.solution.eachproject(sln) do
			table.insert(sortedprojs, prj)
		end

		table.sort(sortedprojs, projkindsort)

		for _, prj in ipairs(sortedprojs) do
			local fname = premake.project.getbasename(prj.name, '%%.bff')
			fname = path.join(prj.location, fname)
			fname = path.getrelative(sln.location, fname)
			_p('#include "%s"', fname)
		end
		_p('')

		_p('.ProjectVariants = {')
		for _, plat in ipairs(sln.platforms) do
			for _, cfg in ipairs(sln.configurations) do
			_p(1, "'%s-%s',", cfg, plat)
			end
		end
		_p('}')
		_p('')

		_p('ForEach(.Variant in .ProjectVariants)')
		_p('{')
		_p(1, "Alias('all-$Variant$')")
		_p(1, '{')
		_p(2, '.Targets = {')
		for _, prj in ipairs(sortedprojs) do
			_p(3, "'%s-$Variant$',", prj.name)
		end
		_p(2, '}')
		_p(1, '}')
		_p('}')
	end
