Post_Processing = class(function(pp)
  pp.config = {}
  pp.decoding = {
	{
		["name"]="MXAO", 
		["bits"]=2, 
		["action"]="set", 
		["steps"]=0, 
		["pp_index"]={5, 6}, 
		["off"]={0,0}, 
		["on"]={1,1}
	},
	{
		["name"]="Depth of Field", 
		["bits"]=2, 
		["action"]="fade", 
		["steps"]=1, 
		["pp_index"]={22}, 
		["off"]={1}, 
		["on"]={0}, 
		["step"]={-0.5}
	},
	{
		["name"]="Motion Blur", 
		["bits"]=2, 
		["action"]="motion", 
		["steps"]=0, 
		["pp_index"]={13,14}, 
		["off"]={0,0}, 
		["on"]={1,1}
	},
	{
		["name"]="Lens Flare", 
		["bits"]=1, 
		["action"]="set", 
		["steps"]=0, 
		["pp_index"]={8}, 
		["off"]={0}, 
		["on"]={1}
	},
	{
		["name"]="Lens Dirt", 
		["bits"]=1, 
		["action"]="fade", 
		["steps"]=0, 
		["pp_index"]={21}, 
		["off"]={1}, 
		["on"]={0}
	},
	{
		["name"]="Visor", 
		["bits"]=1, 
		["action"]="set", 
		["steps"]=0, 
		["pp_index"]={20}, 
		["off"]={0}, 
		["on"]={1}
	},
	{
		["name"]="3D", 
		["bits"]=2, 
		["action"]="set", 
		["steps"]=0, 
		["pp_index"]={28,29,30}, 
		["off"]={0,0,0}, 
		["on"]={1,1,1}
	},
	{
		["name"]="Accessability", 
		["bits"]=2, 
		["action"]="set", 
		["steps"]=0, 
		["pp_index"]={31,32,33}, 
		["off"]={0,0,0}, 
		["on"]={1,1,1}
	},
	{
		["name"]="Internal",
		["bits"]=1,
		["action"]="script",
		["script"]="pp_internal_post_processes_enabled",
		["pp_index"]={},
	},
	{
		["name"]="External",
		["bits"]=1,
		["action"]="script",
		["script"]="pp_external_post_processes_enabled",
		["pp_index"]={},
	},
	{
		["name"]="Anti-Aliasing",
		["bits"]=1,
		["action"]="script",
		["script"]="pp_fxaa_enabled",
		["pp_index"]={},
	},
	{
		["name"]="GBuffer",
		["bits"]=1,
		["action"]="script",
		["script"]="rasterizer_gbuffer_enabled",
		["pp_index"]={},
	},
	{
		["name"]="Depth Fade",
		["bits"]=1,
		["action"]="script",
		["script"]="rasterizer_effect_depth_fade",
		["pp_index"]={},
	},
	{
		["name"]="Bloom",
		["bits"]=1,
		["action"]="bloom",
		["pp_index"]={},
	},
  }
end)
-------------------------------------------------------------------
-- Encoding based off of https://github.com/yumiris/SPV3/issues/3
-- https://raw.githubusercontent.com/yumiris/SPV3/master/doc/shaders.txt
function Post_Processing:decode_from_f1()
  if (map == "ui" or map == "err") then return -1 end
  pp_settings = math.floor(Halo:get_global_f(1)) --F variables are stored in halo as real's (and, collected from halo as floats); convert to integer
  Halo:Print("DBG: ".. pp_settings)

  --MXAO
  if (pp_settings & 1) == 1 then --1b --1
    Halo:Print("MXAO Off")
    execute_script("pp_set_effect_instance_active 5 0")
    execute_script("pp_set_effect_instance_active 6 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --10b --2
    Halo:Print("MXAO Low")
    execute_script("pp_set_effect_instance_active 5 0")
    execute_script("pp_set_effect_instance_active 6 1")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --100b --4
    Halo:Print("MXAO High")
    execute_script("pp_set_effect_instance_active 5 1")
    execute_script("pp_set_effect_instance_active 6 0")
  end
  pp_settings = (pp_settings >> 1)
  
  --DOF
  if (pp_settings & 1) == 1 then --1000b --8
    Halo:Print("DOF Off")
	execute_script("pp_set_effect_instance_fade 22 1 1 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  if (pp_settings & 1) == 1 then --10000b --16
    Halo:Print("DOF Low")
	execute_script("pp_set_effect_instance_fade 22 0.5 0.5 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --100000b --32
    Halo:Print("DOF High")
	execute_script("pp_set_effect_instance_fade 22 0 0 0")
  end
  pp_settings = (pp_settings >> 1)
  
  --Motion Blur
  if (pp_settings & 1) == 1 then --1000000b --64
    Halo:Print("Motion Blur Off")
    execute_script("pp_set_effect_instance_active 13 0")
    execute_script("pp_set_effect_instance_active 14 0")
    execute_script("pp_motion_blur_enabled 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --10000000b --128
    Halo:Print("Motion Blur Built-In")
    execute_script("pp_set_effect_instance_active 13 0")
    execute_script("pp_set_effect_instance_active 14 0")
    execute_script("pp_motion_blur_enabled 1")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --100000000b --256
    Halo:Print("Motion Blur Low")
    execute_script("pp_set_effect_instance_active 13 1")
    execute_script("pp_set_effect_instance_active 14 0")
    execute_script("pp_motion_blur_enabled 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --1000000000b --512
    Halo:Print("Motion Blur High")
    execute_script("pp_set_effect_instance_active 13 0")
    execute_script("pp_set_effect_instance_active 14 1")
    execute_script("pp_motion_blur_enabled 0")
  end
  pp_settings = (pp_settings >> 1)
  
  --Dynamic Lens Filter
  if (pp_settings & 1) == 1 then --10000000000b --1024
    Halo:Print("Dynamic Lens Filter Off")
    execute_script("pp_set_effect_instance_active 8 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --100000000000b --2048
    Halo:Print("Dynamic Lens Filter On")
    execute_script("pp_set_effect_instance_active 8 1")
  end
  pp_settings = (pp_settings >> 1)
  
  
  --Volumetric Lighting
  if (pp_settings & 1) == 1 then --1000000000000b --4096
    Halo:Print("Volumetric Lighting Off")
    execute_script("pp_set_effect_instance_fade 21 1 1 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --10000000000000b --8192
    Halo:Print("Volumetric Lighting On")
    execute_script("pp_set_effect_instance_fade 21 0 0 0")
  end
  pp_settings = (pp_settings >> 1)
  
  --Lens Dirt
  if (pp_settings & 1) == 1 then --100000000000000b --16384
    Halo:Print("Lens Dirt Off")
    execute_script("pp_set_effect_instance_active 9 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --1000000000000000b --32768
    Halo:Print("Lens Dirt On")
    execute_script("pp_set_effect_instance_active 9 1")
  end
  pp_settings = (pp_settings >> 1)
  
  --HudV5 Visor
  if (pp_settings & 1) == 1 then --10000000000000000b --65536
    Halo:Print("HudV5 Visor Off")
    execute_script("pp_set_effect_instance_active 20 0")
  end
  pp_settings = (pp_settings >> 1)
  
  if (pp_settings & 1) == 1 then --100000000000000000b --131072
    Halo:Print("HudV5 Visor On")
    execute_script("pp_set_effect_instance_active 20 1")
  end
  pp_settings = (pp_settings >> 1)
  
  
  --3D
  if (pp_settings & 1) == 1 then --1000000000000000000b --262144
    Halo:Print("3D Off")
    execute_script("pp_set_effect_instance_active 28 0")
    execute_script("pp_set_effect_instance_active 29 0")
    execute_script("pp_set_effect_instance_active 30 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  if (pp_settings & 1) == 1 then --10000000000000000000b --524288
    Halo:Print("3D Anaglyph")
    execute_script("pp_set_effect_instance_active 28 1")
    execute_script("pp_set_effect_instance_active 29 0")
    execute_script("pp_set_effect_instance_active 30 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  if (pp_settings & 1) == 1 then --100000000000000000000b --1048576
    Halo:Print("3D Interleave")
    execute_script("pp_set_effect_instance_active 28 0")
    execute_script("pp_set_effect_instance_active 29 1")
    execute_script("pp_set_effect_instance_active 30 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  
  if (pp_settings & 1) == 1 then --1000000000000000000000b --2097152
    Halo:Print("3D Side-By-Side")
    execute_script("pp_set_effect_instance_active 28 0")
    execute_script("pp_set_effect_instance_active 29 0")
    execute_script("pp_set_effect_instance_active 30 1")
  end
  pp_settings = (pp_settings >> 1)
  
  
  --Color Blind
  if (pp_settings & 1) == 1 then --10000000000000000000000b --4194304
    Halo:Print("Color Blind Off")
    execute_script("pp_set_effect_instance_active 31 0")
    execute_script("pp_set_effect_instance_active 32 0")
    execute_script("pp_set_effect_instance_active 33 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  if (pp_settings & 1) == 1 then --100000000000000000000000b --8388608
    Halo:Print("Color Blind Protanopia")
    execute_script("pp_set_effect_instance_active 31 1")
    execute_script("pp_set_effect_instance_active 32 0")
    execute_script("pp_set_effect_instance_active 33 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  if (pp_settings & 1) == 1 then --1000000000000000000000000b --16777216
    Halo:Print("Color Blind Deuteranopes")
    execute_script("pp_set_effect_instance_active 31 0")
    execute_script("pp_set_effect_instance_active 32 1")
    execute_script("pp_set_effect_instance_active 33 0")
  end
  pp_settings = (pp_settings >> 1)
  
  
  
  if (pp_settings & 1) == 1 then --10000000000000000000000000b --33554432
    Halo:Print("Color Blind Tritanopes")
    execute_script("pp_set_effect_instance_active 31 0")
    execute_script("pp_set_effect_instance_active 32 0")
    execute_script("pp_set_effect_instance_active 33 1")
  end
  pp_settings = (pp_settings >> 1)
end

function Post_Processing:write_json()
  local User = os.getenv("USERPROFILE")
  os.execute("mkdir \"" .. User .. "\\Documents\\My Games\\Halo CE\\SPV3\\\"")
  local file = io.open(User .. "\\Documents\\My Games\\Halo CE\\SPV3\\postprocessing.JSON", "w+")
  if file ~= nil then
  file:write(JSON:encode_pretty(self.config))
  file:flush()
  file:close()
  end
end
function Post_Processing:initialize()
  self.config = {
	["MXAO"]={["level"]=2},
	["Depth of Field"]={["level"]=2},
	["Motion Blur"]={["level"]=3},
	["Lens Flare"]={["level"]=1},
	["Lens Dirt"]={["level"]=1},
	["Visor"]={["level"]=1},
	["3D"]={["level"]=0},
	["Accessability"]={["level"]=0},
	["Internal"]={["level"]=1},
	["External"]={["level"]=1},
	["GBuffer"]={["level"]=1},
	["Depth Fade"]={["level"]=1},
	["Bloom"]={["level"]=1},
	["Anti-Aliasing"]={["level"]=1},
  }
end
function Post_Processing:load_json()
  local User = os.getenv("USERPROFILE")
  local file = io.open(User .. "\\Documents\\My Games\\Halo CE\\SPV3\\postprocessing.JSON", "r")
  if file == nil then
	Halo:Print("Post Process JSON Not found! Initializing new JSON at: ")
	Halo:Print("  " .. User .. "\\Documents\\My Games\\Halo CE\\SPV3\\postprocessing.JSON")
	self:initialize()
	self:write_json()
  else
    self.config = JSON:decode(file:read("*all"))
	file:close()
  end
  self:decode(1)
end

function Post_Processing:load_bin()
  local file = io.open(os.getenv("APPDATA") .."\\SPV3\\postprocessing.bin", "r")
  if file == nil then
	Halo:Print("Post Process BIN Not found! Falling back to JSON!")
	self:load_json()
	--self:initialize()
	--self:write_json()
  else
    --local raw = file:read("*all")
	self.config = {}
	-- self.config["Internal"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["External"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["GBuffer"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Depth Fade"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Bloom"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Lens Flare"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Lens Dirt"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Anti-Aliasing"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Visor"] = {["level"] = (raw & 1)}
	-- raw = raw >> 1
	-- self.config["Motion Blur"] = {["level"] = (raw & 3)}
	-- raw = raw >> 2
	-- self.config["MXAO"] = {["level"] = (raw & 3)}
	-- raw = raw >> 2
	-- self.config["Depth of Field"] = {["level"] = (raw & 3)}
	-- raw = raw >> 2
	-- self.config["3D"] = {["level"] = (raw & 3)}
	-- raw = raw >> 2
	-- self.config["Accessability"] = {["level"] = (raw & 3)}
	-- raw = raw >> 2
	self.config["Internal"] = {["level"] = (file:read(1))}
	self.config["External"] = {["level"] = (file:read(1))}
	self.config["GBuffer"] = {["level"] = (file:read(1))}
	self.config["Depth Fade"] = {["level"] = (file:read(1))}
	self.config["Bloom"] = {["level"] = (file:read(1))}
	self.config["Lens Flare"] = {["level"] = (file:read(1))}
	self.config["Lens Dirt"] = {["level"] = (file:read(1))}
	self.config["Anti-Aliasing"] = {["level"] = (file:read(1))}
	self.config["Visor"] = {["level"] = (file:read(1))}
	self.config["Motion Blur"] = {["level"] = (file:read(1))}
	self.config["MXAO"] = {["level"] = (file:read(1))}
	self.config["Depth of Field"] = {["level"] = (file:read(1))}
	self.config["3D"] = {["level"] = (file:read(1))}
	self.config["Accessability"] = {["level"] = (file:read(1))}
	file:close()
	self:write_json()
  end
  self:decode(1)
end

function Post_Processing:decode(version)
  if (map == "ui" or map == "err") then return -1 end
  if version ~= 1 then return -1 end
  
  if version == 1 then
	  for _,v in pairs(self.decoding) do
		parsing = self.config[v["name"]]["level"]--(pp_settings & v[2])
		if parsing == nil then --If config is unknown, add as off and write new file
		  parsing = 0
		  self.config[v["name"]] = {["level"]=0}
		  self:write_json()
		end
		Halo:Print("Parsing PP " .. v["name"])
		if parsing == 0 then --if value is OFF
		  for idx,v2 in pairs(v["pp_index"]) do
			if v["action"] == "set" then --Turn SETs to default value
				execute_script("pp_set_effect_instance_active ".. v2 .. " " .. v["off"][idx])
			elseif v["action"] == "fade" then --Fade Fades to default value
				execute_script("pp_set_effect_instance_fade ".. v2 .. " " .. v["off"][idx] .. " " .. v["off"][idx] .. " 0" )
			elseif v["action"] == "motion" then --Turn Set motion, and built in motion.
				execute_script("pp_set_effect_instance_active ".. v2 .. " " .. v["off"][idx])
				execute_script ("pp_motion_blur_enabled 0")
			end
		  end
		else
		  if parsing == 1 and v["action"] == "motion" then --Built in Motion - special case.
			for idx,v2 in pairs(v["pp_index"]) do execute_script("pp_set_effect_instance_active ".. v2 .. " " .. v["off"][idx]) end
			execute_script ("pp_motion_blur_enabled 1")
		  else
			local val = 0
			  for i = 1,#v["pp_index"],1 do
				if v["steps"] == 0 then --Not incremental applications
				  if i == parsing then val = v["on"][i] else val = v["off"][i] end
				else --incremental
				  if parsing <= v["steps"] then
					val = v["off"][i] + (v["step"][i] * parsing)
				  else
					val = v["on"][i]
				  end
				end
				if v["action"] == "set" then --Turn SETs to val
					execute_script("pp_set_effect_instance_active ".. v["pp_index"][i] .. " " .. val)
				elseif v["action"] == "fade" then --Fade Fades to value
					execute_script("pp_set_effect_instance_fade ".. v["pp_index"][i] .. " " .. val .. " " .. val .. " 0" )
				elseif v["action"] == "motion" then --Turn Set motion, and built in motion.
					execute_script("pp_set_effect_instance_active ".. v["pp_index"][i] .. " " .. val)
					execute_script ("pp_motion_blur_enabled 0")
				end
			  end
		  end
		end
	    if v["action"] == "script" then
			execute_script(v["script"] .. " " .. (parsing & 1))
		elseif v["action"] == "bloom" then
			execute_script("pp_bloom_set_exposure " .. parsing .. " 5")
		end
	  end
  end
end

PostProcessing = Post_Processing()