#Conditional Hooks
$Application: FS2_Open

$On Game Init:
[

axemParse = {}

function axemParse:Open(file, directory)	--Load a file into a table

	directory = directory or "data/config"

	local t = {}	--Table used to store the file, one line per table element
		
		if cf.fileExists(file,directory,true) then		--Check that the file exists		
			local thisFile = cf.openFile(file,"rb",directory)	--Open the file
			local i = 1 --Setting up the line number
			
			while true do
				local line = thisFile:read("*l") --Read a line

				if line == nil then break end --If we hit the end, break out
			
				if line ~= "" then
					line = line:gsub("\\n","\n") --Replace instances with a literal \n with a real line break
					line = line:gsub("\\t","\t") --Replace instances with a literal \t with a real tab
					t[i] = line
					i = i+1
				end
			
			end
			
			thisFile:close()	--Close the file
			ba.print("AXEMPARSE: LOAD SUCESSFUL!\n")
			return t		--Return the table
		else
			ba.print("AXEMPARSE: SOMETHING WENT HORRIBLY WRONG!\n")
			--ba.error("Problems loading file " .. file)
			return false	--If the file hasn't been loaded, return false
		end
	
end

function axemParse:ToTable(file) --Returns a table!!

	local f = axemParse:Open(file)	-- The raw data file, its a table but needs some refinement
	local fLength = #f
	local finalTable = {}			-- Our end table
	local index = 0
	
	ba.print("BEGINNING PARSE OF: " .. file .. "\n")
	

	for i=1, fLength do
	
		local line = f[i]
		
		if line ~= nil or string.find(line, "%") == 1 then --no need for empty lines or comments
			
			if string.find(line, "@") then
				local j = string.find(line, "@") --Find out where our special strings are
				local k = string.find(line, ":")
					
				if j ~= nil and k ~= nil then
					if string.sub(line,j+1,k-1) == "Index" then --Index is the only special case
						
						if tonumber(string.sub(line,k+2)) ~= nil then
							index = tonumber(string.sub(line,k+2))
						else
							index = index + 1
						end
						
						ba.print("INDEX: " .. index .. "\n")
					end
					
					if string.sub(line,j+1,k-1) ~= "Index" and index ~= 0 then
						local keyString = string.sub(line,j+1,k-1)
						local fieldContent = string.sub(line, k+2)
						
						if finalTable[index] == nil then
							finalTable[index] = {}
						end
						ba.print("KEYSTRING: \"" .. keyString .. "\"\n")
						ba.print("CONTENT: \"" .. fieldContent .. "\"\n")
						
						if string.lower(fieldContent) == "true" then	--It might be a boolean!
							finalTable[index][keyString] = true
						elseif string.lower(fieldContent) == "false" then
							finalTable[index][keyString] = false
						elseif type(fieldContent) == "number" then
							finalTable[index][keyString] = tonumber(fieldContent)
						else
							finalTable[index][keyString] = fieldContent
						end
						
					end
				end	
			end
		end
	
	end
	return finalTable

end

function axemParse:Write(t, filename, path)

	local tt = {}

	local file = cf.openFile(filename, "w+", path)
	
	for i = 1, #t do
	
		tt = t[i]
		
		file:write("@Index: \n")
		
		for key,value in pairs(tt) do
			ba.print("Attempting to write to index " .. i .. ": " .. key .. ": " .. tostring(value) .. "\n")
			file:write("@" .. key .. ": " .. tostring(value) .. "\n")
		end
		
		file:write("\n")
	
	end
	
	file:close()

end

function axemParse:Validate(reference, input, expectedtype, optional)

	if not input and optional then
		return true
	elseif type(input) ~= expectedtype then
		ba.warning("Invalid entry for " .. reference .. ", expected a " .. expectedtype)
	end

end

function axemParse:ReadJSON(file, path)

	ba.print("Beginning JSON Parse for " .. file .. "\n")

	local json = require ("dkjson")
	local t = nil
	
	if path == nil then
		path = "data/config"
		ba.print("No path specified, assuming data/config...\n")
	else
		ba.print("Custom path specified, using " .. path .. "\n")
	end
	
	if cf.fileExists(file,path,true) then
	
		ba.print("File exists, decoding...")
	
		local thisFile = cf.openFile(file,"rb",path)
		local contents = thisFile:read("*a")
		
		t = json.decode(contents)
		
		ba.print(" success!\n")
		
		thisFile:close()
	else
		ba.print("File " .. file .. " does not exist! Here be dragons!\n")
		t = {}
	end
	
	return t

end

function axemParse:WriteJSON(t, filename, path)

	ba.print("Beginning JSON Write for " .. filename .. "\n")

	local json = require ("dkjson")
	
	if path == nil then
		path = "data/config"
		ba.print("No path specified, assuming data/config...\n")
	else
		ba.print("Custom path specified, using " .. path .. "\n")
	end
	
	local file = cf.openFile(filename, "w+", path)
	
	file:write(json.encode(t))
	
	ba.print("Write complete, closing file.\n")
	
	file:close()

end

function SDX(key, value, sexp, campaignonly, suffix) --Save Data for purposes of eXchanging between campaigns

	if campaignonly then
		campaignonly = mn.isInCampaign()
	else
		campaignonly = not campaignonly
	end
	
	if campaignonly then

		local t = {}
		
		if not suffix then
			suffix = "-sdx"
		end

		--generate SDX file name
		local filename = ba.getCurrentPlayer():getName() .. suffix .. ".sav"
		
		--load sdx data file if available, if not create it
		t = axemParse:ReadJSON(filename)
		
		--should we grab the value from a sexp variable instead?
		if sexp then
			if mn.SEXPVariables[value]:isValid() then
				value = mn.SEXPVariables[value].Value
			else
				value = nil
			end
		end
		
		if not value then
			value = "NULL"
		end
		
		--add data to table
		ba.print("SDX WRITE: Key: " .. key .. " = " .. value .. ", to file " .. filename .. "\n")
		t[key] = value
		
		--export as json file
		axemParse:WriteJSON(t, filename)
	
	end

end

function LDX(key, suffix) -- Load Data for purposes of eXchanging between campaigns

	local t = {}
	
	if not suffix then
		suffix = "-sdx"
	end

	--generate SDX file name
	local filename = ba.getCurrentPlayer():getName() .. suffix .. ".sav"
	
	--load sdx data file if available, if not return
	t = axemParse:ReadJSON(filename, path)
	
	if not t then
		return
	end
	
	return t[key]

end

function CDX(campaignonly, suffix) -- Clears saved data

	if campaignonly then
		campaignonly = mn.isInCampaign()
	else
		campaignonly = not campaignonly
	end

	if campaignonly then

		if not suffix then
			suffix = "-sdx"
		end
		

		local filename = ba.getCurrentPlayer():getName() .. suffix .. ".sav"
		
		if cf.fileExists(filename,"data/config", true) then
			deleteFile(filename, "data/config")
		end

	end
end

function trim(str)
	return str:find'^%s*$' and '' or str:match'^%s*(.*%S)'
end

function removeComments(line)
	local cut = line:find(";") -- there's gotta be something more robust than that hack job
	if (cut == nil) then
		return line
	else
		return line:sub(0, cut - 1)
	end
end

function extractLeft(attribute)
	local line = attribute
	local cut = string.find(line, ":")
	if (cut == nil) then
		return trim(line)
	else
		return trim(string.sub(line, 2, cut - 1))
	end
end

function extractRight(attribute)
	local line = attribute
	local cut = string.find(line, ":")
	if (cut == nil) then
		return trim(line)
	else
		return trim(string.sub(line, cut + 1))
	end
end

-- copied from lua-user wiki
function split(str, pat)
	local t = {}  -- NOTE: use {n = 0} in Lua-5.0
	local fpat = "(.-)" .. pat
	local last_end = 1
	local s, e, cap = str:find(fpat, 1)
	while s do
		if s ~= 1 or cap ~= "" then
			cap = trim(cap)
			table.insert(t,cap)
		end
		last_end = e+1
		s, e, cap = str:find(fpat, last_end)
	end
	if last_end <= #str then
		cap = str:sub(last_end)
		table.insert(t, cap)
	end
	return t
end

----------------------
--- Core Functions ---
----------------------

function stuffAttribute(attributeTable, value)
	if (isList == nil) then
		attributeTable = value
	else
		attributeTable = split(value, ",")
	end
end

--[[
	@return a lua table containing data from the parsed table.
]]--
function parseTableFile(filePath, fileName)
	local tableObject = {}

	if cf.fileExists(fileName, filePath, true) then
		local file = cf.openFile(fileName, "r", filePath)
		
		local hasCategory = false
		local line = file:read("*l")
		while (not (line == nil)) do
			line = removeComments(line)
			line = trim(line)
			local attribute = extractLeft(line)
			local value = extractRight(line)
			isCat = string.find(line, "#(.)+:")
			isAttr = string.find(line, "($)")
			isSubAttr = string.find(line, "+")
			isList = string.find(line, ",")
			--
			ba.print("[parse.lua] Parsing line: "..line)
			if not (isCat == nil) then
				hasCategory = true
			elseif not (isAttr == nil) then
				if (attribute == "Name") then
					name = value
					if (hasCategory) then
						tableObject[category][name] = {}
					else
						tableObject[name] = {}
					end
					ba.print("[parse.lua] Name="..name)
				else
					currentAttribute = attribute -- save attribute name in case we run into sub attributes
					if (hasCategory) then --TODO: refactor into functions
						stuffAttribute(tableObject[category][name][attribute], value)
					else
						stuffAttribute(tableObject[name][attribute], value)
					end
					ba.print("[parse.lua] name="..name.."; attribute="..attribute.."; value="..value)
				end
			elseif not (isSubAttr == nil) then
				-- initialize if needs be
				if (hasCategory and tableObject[category][name][currentAttribute]['sub'] == nil) then
					tableObject[category][name][currentAttribute]['sub'] = {}
				elseif (tableObject[name][currentAttribute]['sub'] == nil) then
					tableObject[name][currentAttribute]['sub'] = {}
				end
				
				if (hasCategory) then
					stuffAttribute(tableObject[category][name][currentAttribute]['sub'][attribute], value)
				else
					stuffAttribute(tableObject[name][currentAttribute]['sub'][attribute], value)
				end
				ba.print("[parse.lua] name="..name.."; current attribute="..currentAttribute.."; sub attribute="..attribute.."; value="..value)
			end
			--
			line = file:read("*l")
		end
	else
		ba.warning("[parse.lua] Table file not found: "..filePath..fileName)
	end

	return tableObject
end

]

#End