local LevelStartX = 2450
local LevelStartY = 3750
local SaveFilePath = GetMapFolder() .. "\\save.txt"

local MENU = {
	Main = 1,
	NewGame = 2,
	LoadGame = 3,
	Help = 4,
	Credits = 5
}

local MENU_ELEM = {
	Main = {
		NewGame = 1,
		LoadGame = 2,
		AspectRatio = 3,
		Help = 4,
		Credits = 5
	},
	NewGame = {
		Normal = 1,
		Easy = 2,
		Hardcore = 3,
		Back = 4
	},
	LoadGame = {
		SavePoint1 = 1,
		SavePoint2 = 2,
		Boss = 3,
		Back = 4
	},
	Help = {
		Back = 1
	},
	Credits = {
		Back = 1
	}
}

local FRAME = {
	Normal = 1,
	Selected = 2,
	Disabled = 3
}

local function destroyMenuElements(self)
	for _, subMenu in ipairs(self.menu) do
		for _, elem in ipairs(subMenu) do
			elem:Destroy()
		end
	end
	self.title:Destroy()
	self.leftIndicator:Destroy()
	self.rightIndicator:Destroy()
end

function startGame(self, mode)
	if not mode then
		self.detectorHook.Difficulty = 0
		self.State = 1000
		return
	end

	if mode == "Easy" then
		CreateObject{name="EasyMode"}
		self.detectorHook.Difficulty = 1
		self.State = 1000
		return
	end

	if mode == "Hardcore" then
		CreateObject{name="HardcoreMode"}
		self.detectorHook.Difficulty = 2
		self.State = 1000
		return
	end
end

function loadGameFromSP(self, sp)
	local saveSystem = GetObject(2672)
	local success = saveSystem:canLoadSavePoint(sp)
	if success then
		destroyMenuElements(self)
		saveSystem:loadSavePoint(sp)
		CreateObject{name="ArtifactDisplay"}
		self:Destroy()
	end
end

function createMenuElement(self, offsetY, image)
	return CreateHUDObject{
		X = self.centerX,
		Y = self.centerY + offsetY,
		Z = 11011,
		logic = "DoNothingNormal",
		image = image,
		DrawFlags = ffi.new("DrawFlags_t", DrawFlags.NoDraw)
	}
end

function gotoSubMenu(self, subMenu, choice)
	if not subMenu or subMenu <= 0 or subMenu > self.menusNo then
		return
	end

	local firstSelected = false

	for i, k in ipairs(self.menu) do
		local noDraw = i ~= subMenu
		for j, elem in ipairs(k) do
			elem.DrawFlags.NoDraw = noDraw

			if not noDraw and elem.I ~= FRAME.Disabled then
				if (choice and j == choice) or (not choice and not firstSelected) then
					elem:SetFrame(FRAME.Selected)
					self.leftIndicator.Y = elem.Y
					self.rightIndicator.Y = elem.Y
					self.currentSelection = j
					firstSelected = true
				else
					elem:SetFrame(FRAME.Normal)
				end
			end
		end
	end

	self.title:SetFrame(subMenu)

	self.State = subMenu
end

function selectNext(self)
	local currentSubMenu = self.menu[self.State]
	local numberOfChoices = #currentSubMenu

	if numberOfChoices == 1 then
		return
	end

	local obj = currentSubMenu[self.currentSelection]
	if not obj then
		gotoSubMenu(self, self.State)
		return
	else
		obj:SetFrame(FRAME.Normal)
	end

	local next = self.currentSelection + 1
	local foundNext = false

	repeat
		for i, elem in ipairs(currentSubMenu) do
			if next > numberOfChoices then
				next = 1
			end
			if i == next then
				if elem.I == FRAME.Disabled then
					next = next + 1
				else
					elem:SetFrame(FRAME.Selected)
					self.leftIndicator.Y = elem.Y
					self.rightIndicator.Y = elem.Y
					self.currentSelection = i
					foundNext = true
					break
				end
			end
		end
	until foundNext
	PlaySound"GAME_CLICK"
end

function selectPrevious(self)
	local currentSubMenu = self.menu[self.State]
	local numberOfChoices = #currentSubMenu

	if numberOfChoices == 1 then
		return
	end

	local obj = currentSubMenu[self.currentSelection]
	if not obj then
		gotoSubMenu(self, MENU.Main)
		return
	else
		obj:SetFrame(FRAME.Normal)
	end

	local prev = self.currentSelection - 1
	local foundPrev = false

	repeat
		for i, elem in ipairs(currentSubMenu) do
			if prev <= 0 then
				prev = numberOfChoices
			end
			if i == prev then
				if elem.I == FRAME.Disabled then
					prev = prev - 1
				else
					elem:SetFrame(FRAME.Selected)
					self.leftIndicator.Y = elem.Y
					self.rightIndicator.Y = elem.Y
					self.currentSelection = i
					foundPrev = true
					break
				end
			end
		end
	until foundPrev
	PlaySound"GAME_CLICK"
end

function main(self)
	local claw = GetClaw()

	if self.State == 0 then
        self.Flags.AlwaysActive = true
		self.KeyPressDelay = 0
		self.screenW, self.screenH = GetResolution()
		self.centerX = math.floor(self.screenW/2)
		self.centerY = math.floor(self.screenH/2)
		self.detectorHook = GetObject(3206)

		claw.State = ClawStates.Freeze
		self.leftIndicator = CreateHUDObject{
			X = self.centerX - 300,
			Y = self.centerY - 80,
			Z = 11011,
			logic = "AniCycle",
			image = "CUSTOM_ICESHIELD",
			animation = "CUSTOM_CYCLE72"
		}
		self.rightIndicator = CreateHUDObject{
			X = self.centerX + 300,
			Y = self.centerY - 80,
			Z = 11011,
			logic = "AniCycle",
			image = "CUSTOM_FIRESHIELD",
			animation = "CUSTOM_CYCLE72"
		}

		self.title = createMenuElement(self, -120, "CUSTOM_STARTMENU_TITLES")
		self.title.DrawFlags.NoDraw = false

		self.menu = {
			{
				createMenuElement(self, -80, "CUSTOM_STARTMENU_START"),
				createMenuElement(self, -40, "CUSTOM_STARTMENU_LOAD"),
				createMenuElement(self, 0, "CUSTOM_STARTMENU_ASPECTRATIO"),
				createMenuElement(self, 40, "CUSTOM_STARTMENU_HELP"),
				createMenuElement(self, 80, "CUSTOM_STARTMENU_CREDITS")
			},
			{
				createMenuElement(self, -60, "CUSTOM_STARTMENU_NORMAL"),
				createMenuElement(self, -20, "CUSTOM_STARTMENU_EASY"),
				createMenuElement(self, 20, "CUSTOM_STARTMENU_HARDCORE"),
				createMenuElement(self, 60, "CUSTOM_STARTMENU_BACK")
			},
			{
				createMenuElement(self, -60, "CUSTOM_STARTMENU_SAVE1"),
				createMenuElement(self, -20, "CUSTOM_STARTMENU_SAVE2"),
				createMenuElement(self, 20, "CUSTOM_STARTMENU_BOSS"),
				createMenuElement(self, 60, "CUSTOM_STARTMENU_BACK")
			},
			{
				createMenuElement(self, 100, "CUSTOM_STARTMENU_BACK")
			},
			{
				createMenuElement(self, 100, "CUSTOM_STARTMENU_BACK")
			}
		}
		self.menusNo = #self.menu

		if GetGameType() == GameType.SinglePlayer then
			local saveFile = io.open(SaveFilePath, "r")
			if saveFile ~= nil then
				local savedFlags = tonumber(saveFile:read("*line"))
				io.close(saveFile)
				local loadGameSubMenu = self.menu[MENU.LoadGame]
				if AND(savedFlags, 0x10) == 0 then
					loadGameSubMenu[1]:SetFrame(FRAME.Disabled)
				end
				if AND(savedFlags, 0x20) == 0 then
					loadGameSubMenu[2]:SetFrame(FRAME.Disabled)
				end
				if AND(savedFlags, 0x40) == 0 then
					loadGameSubMenu[3]:SetFrame(FRAME.Disabled)
				end
			end
		end

		self.classicAspectRatio = false

		gotoSubMenu(self, MENU.Main)
		self.State = 500
	end

	if self.State == 500 and not KeyPressed"Enter" then
		gotoSubMenu(self, MENU.Main)
	end

	if self.State > 0 and self.State <= self.menusNo then
		if GetInput"Up" and not self.upPressed then
			selectPrevious(self)
			self.upPressed = true
		end
		if not GetInput"Up" and self.upPressed then
			self.upPressed = false
		end
		if GetInput"Down" and not self.downPressed then
			selectNext(self)
			self.downPressed = true
		end
		if not GetInput"Down" and self.downPressed then
			self.downPressed = false
		end
		if (GetInput"Jump" or KeyPressed"Enter") and not self.enterPressed then
			self.choiceConfirmed = true
			PlaySound"GAME_SELECT"
			self.enterPressed = true
		end
		if not GetInput"Jump" and not KeyPressed"Enter" and self.enterPressed then
			self.enterPressed = false
		end
	end

	-- starting the level:
	if self.State == 1000 then
		local resolution = self.classicAspectRatio and 1 or 0
		CreateObject{name="ResChanger", Smarts = resolution}
		self.detectorHook.Resolution = resolution
		self.detectorHook.ScreenW = self.classicAspectRatio and 640 or 864
		self.detectorHook.ScreenH = self.classicAspectRatio and 480 or 486
		CreateHUDObject{
			X = self.detectorHook.ScreenW - 67,
			Y = self.detectorHook.ScreenH - 6,
			Z = 10050,
			logic = "DoNothing",
			image = "CUSTOM_MODEDISPLAY",
			I = self.detectorHook.Difficulty + 1
		}
		CreateObject{name="ArtifactDisplay"}
		Teleport(LevelStartX, LevelStartY)
		SetRespawnPoint(LevelStartX, LevelStartY)
		destroyMenuElements(self)
		claw.State = ClawStates.Stand
		claw:AlignToGround()
		self:Destroy()
		return
	elseif claw.Health > 0 then
		claw.State = ClawStates.Freeze
	end

	if self.State == MENU.Main and self.choiceConfirmed then
		self.choiceConfirmed = false
		local choice = MENU_ELEM.Main
		if self.currentSelection == choice.NewGame then
			gotoSubMenu(self, MENU.NewGame) return
		end
		if self.currentSelection == choice.LoadGame then
			gotoSubMenu(self, MENU.LoadGame) return
		end
		if self.currentSelection == choice.AspectRatio then
			if not self.classicAspectRatio then
				local elem = self.menu[MENU.Main][choice.AspectRatio]
				if not elem then return end
				elem:SetImage"CUSTOM_STARTMENU_ASPECTRATIO43"
				elem:SetFrame(FRAME.Selected)
				self.classicAspectRatio = true
			else
				local elem = self.menu[MENU.Main][choice.AspectRatio]
				if not elem then return end
				elem:SetImage"CUSTOM_STARTMENU_ASPECTRATIO"
				elem:SetFrame(FRAME.Selected)
				self.classicAspectRatio = false
			end
		end
		if self.currentSelection == choice.Help then
			gotoSubMenu(self, MENU.Help) return
		end
		if self.currentSelection == choice.Credits then
			gotoSubMenu(self, MENU.Credits) return
		end
	end

	if self.State == MENU.NewGame and self.choiceConfirmed then
		self.choiceConfirmed = false
		local choice = MENU_ELEM.NewGame
		if self.currentSelection == choice.Normal then
			startGame(self) return
		end
		if self.currentSelection == choice.Easy then
			startGame(self, "Easy") return
		end
		if self.currentSelection == choice.Hardcore then
			startGame(self, "Hardcore") return
		end
		if self.currentSelection == choice.Back then
			gotoSubMenu(self, MENU.Main, MENU_ELEM.Main.NewGame) return
		end
	end

	if self.State == MENU.LoadGame and self.choiceConfirmed then
		self.choiceConfirmed = false
		local choice = MENU_ELEM.LoadGame
		if self.currentSelection == choice.SavePoint1 then
			loadGameFromSP(self, 1) return
		end
		if self.currentSelection == choice.SavePoint2 then
			loadGameFromSP(self, 2) return
		end
		if self.currentSelection == choice.Boss then
			loadGameFromSP(self, 3) return
		end
		if self.currentSelection == choice.Back then
			gotoSubMenu(self, MENU.Main, MENU_ELEM.Main.LoadGame) return
		end
	end

	if self.State == MENU.Help and self.choiceConfirmed then
		self.choiceConfirmed = false
		gotoSubMenu(self, MENU.Main, MENU_ELEM.Main.Help) return
	end

	if self.State == MENU.Credits and self.choiceConfirmed then
		self.choiceConfirmed = false
		gotoSubMenu(self, MENU.Main, MENU_ELEM.Main.Credits) return
	end

end
