local SAVE_FILE_PATH = GetMapFolder() .. "\\save.txt"

local concat = table.concat

local function getStatsTable(self)
	local pd = PData()
	return {
		pd.CollectedSkull,
		pd.CollectedCrown,
		pd.CollectedGecko,
		pd.CollectedScepter,
		pd.CollectedCross,
		pd.CollectedChalice,
		pd.CollectedRing,
		pd.CollectedGoldbar,
		pd.CollectedCoin,
		GetClaw().Score,
		pd.PistolAmmo,
		pd.MagicAmmo,
		pd.TNTAmmo,
		pd.Lives,
		GetClaw().Health,
		self.detector.ArtifactsOwned,
		self.detector.Difficulty,
		self.detector.Resolution
	}
end

local function readStatsNextLine(self)
	local tab = {}
	local line = self.saveFile:read("*l")
	for stat in string.gmatch(line, "[^;]+") do
		table.insert(tab, tonumber(stat))
	end
	return tab
end

local function saveToFile(self)
	self.saveFile = io.open(SAVE_FILE_PATH, "w")
	io.output(self.saveFile)
	io.write(concat{
		self.savedFlags,
		"\n",
		concat(self.statsTable[1], ";"),
		"\n",
		concat(self.statsTable[2], ";"),
		"\n",
		concat(self.statsTable[3], ";")
	})
	io.close(self.saveFile)
end

local function canLoadSavePoint(self, n)
	return self.superCheckpoints[n] and AND(self.savedFlags, bit.lshift(0x10, n-1)) ~= 0
end

local function loadSavePoint(self, n)
	local goldenFlag = self.superCheckpoints[n]
	local savePointX, savePointY = goldenFlag.X, goldenFlag.Y - 32
	local saveData = self.statsTable[n]
	local pd = PlayerData()
	local claw = GetClaw()

	-- set the difficulty first:
	local difficulty = saveData[17]
	self.detector.Difficulty = difficulty
	if difficulty == 2 then
		CreateObject{name = "HardcoreMode"}
	elseif difficulty == 1 then
		CreateObject{name = "EasyMode"}
	end

	self.detector.Resolution = saveData[18]
	if self.detector.Resolution == 1 then
		self.detector.ScreenW = 640
		self.detector.ScreenH = 480
	else
		self.detector.ScreenW = 864
		self.detector.ScreenH = 486
	end
	CreateObject{
		X = savePointX,
		Y = savePointY,
		name = "ResChanger",
		Smarts = self.detector.Resolution
	}


	pd.CollectedSkull 	= saveData[1]
	pd.CollectedCrown 	= saveData[2]
	pd.CollectedGecko 	= saveData[3]
	pd.CollectedScepter = saveData[4]
	pd.CollectedCross 	= saveData[5]
	pd.CollectedChalice = saveData[6]
	pd.CollectedRing 	= saveData[7]
	pd.CollectedGoldbar = saveData[8]
	pd.CollectedCoin 	= saveData[9]
	claw.Score			= saveData[10]
	pd.PistolAmmo 		= saveData[11]
	pd.MagicAmmo 		= saveData[12]
	pd.TNTAmmo 			= saveData[13]
	pd.Lives 			= 10 -- temporarily set lives to max, so increasing the score won't trigger the sound
	self.loadedClawLives = saveData[14]
	claw.Health 		= saveData[15]

	self.detector.ArtifactsOwned = saveData[16]

	for id, artifact in ipairs(self.detector.Artifacts) do
		if AND(self.detector.ArtifactsOwned, bit.lshift(1, id-1)) ~= 0 then
			CreateObject{
				X = savePointX,
				Y = savePointY,
				name = "ArtifactPower:" .. artifact.Logic
			}
			if artifact.Type == "Special" then
				for _id, _artifact in ipairs(self.detector.Artifacts) do
					if _artifact.Type == "Special" then
						table.insert(self.detector.ListOfAlreadyChosen, _id)
					end
				end
			else
				table.insert(self.detector.ListOfAlreadyChosen, id)
			end
		end
	end

	CreateHUDObject{
		X = self.detector.ScreenW - 67,
		Y = self.detector.ScreenH - 6,
		Z = 10050,
		logic = "DoNothing",
		image = "CUSTOM_MODEDISPLAY",
		I = difficulty + 1
	}

	goldenFlag.DrawFlags.NoDraw = true
	goldenFlag.X, goldenFlag.Y = 1, 1
	SetRespawnPoint(savePointX, savePointY)
	Teleport(savePointX, savePointY)
	ClawJump(0)

	self.countTime = GetTime() + 500
	self.State = 2
	return true
end

function main(self)
	if self.State == 0 then
		if GetGameType() == GameType.MultiPlayer then
			self:Destroy()
			return
		end
		self.Flags.AlwaysActive, self.DrawFlags.NoDraw = true, true
		self.detector = GetObject(3206)

		self.saveFile = io.open(SAVE_FILE_PATH, "r")
		if self.saveFile == nil then
			self.saveFile = io.open(SAVE_FILE_PATH, "w")
			io.output(self.saveFile)
			io.write("0\n0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0\n0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0\n0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0;0")
			io.close(self.saveFile)
			self.savedFlags = 0
			self.statsTable = {
				{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
				{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0},
				{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}
			}
		else
			self.savedFlags = self.saveFile:read("*l")
			self.statsTable = {
				readStatsNextLine(self),
				readStatsNextLine(self),
				readStatsNextLine(self)
			}
			io.close(self.saveFile)
		end

		self.superCheckpointTriggered = {false, false, false}
		self.superCheckpoints = {
			GetObject(645),
			GetObject(4297),
			GetObject(2671)
		}
		self.lastSuperCheckpoint = #self.superCheckpoints

		self.canLoadSavePoint = canLoadSavePoint
		self.loadSavePoint = loadSavePoint

		self.countTime = 0

		self.State = 1
	end

	if self.State == 1 then
		for i, cp in ipairs(self.superCheckpoints) do
			if cp.State == 6 and not self.superCheckpointTriggered[i] then
				if not CheatsUsed() then
					TextOut("Your game has been saved!")
					self.statsTable[i] = getStatsTable(self)
					self.savedFlags = OR(self.savedFlags, bit.lshift(0x10, i-1))
					saveToFile(self)
					self.superCheckpointTriggered[i] = true
				else
					TextOut("The game was not saved, because you cheated!")
					self.superCheckpointTriggered[i] = true
				end
				if i == self.lastSuperCheckpoint then
					self:Destroy()
				end
			end
		end
	end

	if self.State == 2 and GetTime() > self.countTime then
		PlayerData().Lives = self.loadedClawLives
		self.State = 1
	end
end
