
-- This will slap a bunch of lua files together and compile them as one file.
-- This merges the local space of all of the files, and allows them o call local variables across file boundaries.



-- Select between two return values based on an if condition.
local function Select(condition,yes,no)
	if condition then return yes else return no end
end

-- Select some functions based on the name they are using. This is for compatibility between Lua versions.
local TableUnpack = Select(table.unpack,table.unpack,unpack)
local StringToFunction = Select(string.load,string.load,load)

-- Turns an if condition into a pure boolean value.
local function ToBool(condition)
	return Select(condition,true,false)
end

-- Returns the boolean obtained from an equivalency check.
local function IsToBool(inval,inval2)
	return inval == inval2
end

-- Returns the boolean from a string type check.
local function IsStringToBool(inval)
	return IsToBool(type(inval),"string")
end

-- Pulls the raw information out of a file, and into a string.
local function ReadFileRaw(inval)
	if IsStringToBool(inval) then
		local infile = io.open(inval,"rb")
		if infile ~= nil then
			local instr = infile:read("*all")
			if instr ~= nil then
				return instr
			end
		end
	end
end

-- Writes or appends a string to a file.
local function WriteToFile(what,where,replace)
	if where == nil then where = "output" end
		local wherefile = io.open(where,"r")
		if wherefile == nil or replace == true then
			if wherefile ~= nil then wherefile:close() end
			wherefile = io.open(where,"w")
		else
			wherefile:close()
			wherefile = io.open(where,"a")
		end
		if wherefile ~= nil then
			wherefile:write(tostring(what) .. "\n")
			wherefile:close()
		else
			print("Failed to write to " .. tostring(where))
		end
end

-- Takes in a file name string and tries to load the equivalent file. If not, returns a failure string.
local function FilenameToFileString(instr,failurestr,prefixstr)
			-- The default failure message is a Lua comment saying which file failed to load.
			failurestr = Select(IsStringToBool(failurestr),failurestr,"-- Failed to read file: \"" .. instr .. "\"")
			prefixstr = Select(IsStringToBool(prefixstr),prefixstr,"\n-- File: \"" .. instr .. "\"\n")
			-- Try to obtain our file.
			local infile = ReadFileRaw(instr)
			-- Return our result string, or a failure string if we don't have one.
			return Select(IsStringToBool(infile),prefixstr .. tostring(infile),failurestr)
end

-- Slap some strings together, if they exist, otherwise return nil.
local function ConcatenateStrings(instr,nextstr,...)
	if IsStringToBool(nextstr) then
		if IsStringToBool(nextstr) then
			return ConcatenateStrings(instr .. nextstr,...)
		end
		return instr
	end
end

-- Slap file strings together, given their names.
local function ConcatenateFileStrings(failurestr,instr,nextstr,...)
	-- Do we have a first filename?
	if IsStringToBool(instr) then
		-- Do we have a second filename?
		if IsStringToBool(nextstr) then
			-- Return a concatenation of the first and next files and recurse.
			return FilenameToFileString(instr,failurestr) .. "\n" .. FilenameToFileString(nextstr,failurestr) .. "\n" .. ConcatenateFileStrings(failurestr,...)
		end
		-- Return the first file from its filename if the second is invalid and recurse.
		return FilenameToFileString(instr) .. ConcatenateFileStrings(failurestr,...)
	elseif IsStringToBool(nextstr) then
		-- Return the second file from its filename if the first is invalid and recurse.
		return FilenameToFileString(instr) .. ConcatenateFileStrings(failurestr,...)
	end
	-- Return an empty string if no valid filenames are available.
	return ""
end

-- Turn a string into a Lua function and execute it with passed arguments, returning the results.
local function LoadFromString(inval,...)
	if inval ~= nil then
		local inval = StringToFunction(inval)
		if inval ~= nil then
			return inval(...)
		end
	end
end

local function OpenTable(intbl)
	return Select(intbl,intbl,{})
end

local function ReturnIfNotLast(inval,nextval,...)
	if nextval == nil then return nil end
	return inval, ReturnIfNotLast(nextval,...)
end


FilesToLoad = Select(FilesToLoad,FilesToLoad,{
	"Lua Logic Modules/Injection Pass/Aliases.lua",
	"Lua Logic Modules/Injection Pass/ConditionalLogic.lua",

	"Lua Logic Modules/Pass 5/Aliases.lua",
	"Lua Logic Modules/Pass 5/ConditionalLogic.lua",
	"Lua Logic Modules/Pass 5/BooleanLogic.lua",
	"Lua Logic Modules/Pass 5/ListLogic.lua",
	"Lua Logic Modules/Pass 5/TableLogic.lua",
	"Lua Logic Modules/Pass 5/NumberLogic.lua",
	"Lua Logic Modules/Pass 5/StringLogic.lua",
	"Lua Logic Modules/Pass 5/OneWayLogic.lua",

	"Lua Logic Modules/Pass 10/Aliases.lua",
	"Lua Logic Modules/Pass 10/ConditionalLogic.lua",
	"Lua Logic Modules/Pass 10/TableLogic.lua",
	"Lua Logic Modules/Pass 10/StringLogic.lua",
	"Lua Logic Modules/Pass 10/OneWayLogic.lua",

	"Lua Logic Modules/Pass 15/Aliases.lua",
	"Lua Logic Modules/Pass 15/ConditionalLogic.lua",
	"Lua Logic Modules/Pass 15/BooleanLogic.lua",
	"Lua Logic Modules/Pass 15/ListLogic.lua",
	"Lua Logic Modules/Pass 15/TableLogic.lua",
	"Lua Logic Modules/Pass 15/NumberLogic.lua",

	"Lua Logic Modules/Pass 20/ConditionalLogic.lua",
	"Lua Logic Modules/Pass 20/TableLogic.lua",

	"Data Logic Modules/Pass 5/BooleanDataLogic.lua",
	"Data Logic Modules/Pass 5/ConditionalDataLogic.lua",
	"Data Logic Modules/Pass 5/ListDataLogic.lua",
	"Data Logic Modules/Pass 5/TableDataLogic.lua",
	"Data Logic Modules/Pass 5/NumberDataLogic.lua",
	"Data Logic Modules/Pass 5/StringDataLogic.lua",
	"Data Logic Modules/Pass 5/FunctionDataLogic.lua",
	"Data Logic Modules/Pass 5/FileDataLogic.lua",
	"Data Logic Modules/Pass 5/OneWayDataLogic.lua",

	"Lua Logic Modules/Pass 20/Aliases.lua",
	"Scripts/Bootstrap.lua",
	ReturnIfNotLast(TableUnpack(OpenTable(arg)))
})

-- Don't set a generic failure message, and load all of our files into a string.

local function ReturnLast(inval,nextval,...)
	if nextval == nil and inval ~= nil then
		return inval
	elseif inval == nil and nextval == nil then
		return ""
	end
	return ReturnLast(nextval,...)
end

-- Put all of the above module files into a string.
local InitializerString = ConcatenateFileStrings(nil,TableUnpack(OpenTable(FilesToLoad)))
-- Set a default for where only the modules listed above will be written to.
local DefaultFileOutput = "ModulesOnly.lua"
WriteToFile(InitializerString,DefaultFileOutput,true)

-- Append any files given as arguments to our string.
InitializerString = InitializerString .. "\n" .. ConcatenateFileStrings(nil,ReturnLast(TableUnpack(OpenTable(arg))))

-- Set a default for where we write the combined file out to.
local DefaultFileOutput = "Combined.lua"
-- Write our file out to that location.
WriteToFile(InitializerString,DefaultFileOutput,true)

-- Load that file with Lua's built-in "dofile" mechanism. This allows us to get any errors printed to screen.
dofile(DefaultFileOutput)
