local hubmap = 100
local secretmap = 27
local finalmap = 28
local sbahjmap = 29

local gatelines = 300
local mplines = 400
local garanztag = 115
local hogantag = 8000

local requirements = {1,4,9,15}
local unlocknames = {"Area 1","Area 2","Area 3","The Finale","Area X"}

local progress = {false,false,false,false,false}
local mapchecks = {}
local voteinfo = {false,0,100,nil}
local playervotes = {}
local hubspotinfo = {false,0,0,0,0}
local didsbahjcecho = false

local currentCecho = { -- quick last second port from subarashii
	text = nil,
	flags = V_YELLOWMAP|V_RETURN8,
	timer = 0
}

addHook("NetVars", function(net)
	progress = net(progress)
	mapchecks = net(mapchecks)
	voteinfo = net(voteinfo)
	playervotes = net(playervotes)
	hubspotinfo = net(hubspotinfo)
	didsbahjcecho = net(didsbahjcecho)
end)

local cv_vote = CV_RegisterVar({
	name = "votetime",
	defaultvalue = "10",
	flags = CV_SAVE|CV_NETVAR,
	PossibleValue = {MIN = -1, MAX = 3600}
})

local cv_emblems = CV_RegisterVar({
	name = "useemblems",
	defaultvalue = "yes",
	flags = CV_NETVAR|CV_NOTINNET,
	PossibleValue = CV_YesNo
})

addHook("MobjThinker", function(mo)
	for player in players.iterate do
		if player.exiting != 0
		and mo.frame == F
		and not (multiplayer or modifiedgame or cv_emblems.value == 0)
			P_TeleportMove(mo, player.mo.x, player.mo.y, player.mo.z)
		end
	end
end, MT_EMBLEM)

local function getvotecount(x)
	local yesvotes = 0
	local novotes = 0
	local totalvotes = 0
	for k,v in pairs(playervotes)
		if v == true
			yesvotes = $1 + 1
			totalvotes = $1 + 1
		elseif v == false
			novotes = $1 + 1
			totalvotes = $1 + 1
		end
	end
	if x == "yes"
		return yesvotes
	elseif x == "no"
		return novotes
	else
		return totalvotes
	end
end

local function getplayercount()
	local playercount = 0
	for player in players.iterate do
		if player.bot == 0
			playercount = $1 + 1
		end
	end
	return playercount
end

local function gettotalbeaten()
	local totalbeaten = 0
	for k,v in pairs(mapchecks)
		if v == true
			totalbeaten = $1 + 1
		end
	end
	return totalbeaten
end

local function finishvote()
	if voteinfo[1] != true return end
	local wantedmap = voteinfo[3]
	local startedby = voteinfo[4]
	
	if hubspotinfo[1] == true
		if getvotecount("yes") > getvotecount("no")
		or cv_vote.value == -1
			G_ExitLevel(wantedmap, 1)
		else
			currentCecho.text = "Vote failed!"
			currentCecho.flags = V_YELLOWMAP|V_RETURN8
			currentCecho.timer = 6*TICRATE
			if startedby and startedby.valid
				P_TeleportMove(startedby.mo,hubspotinfo[2],hubspotinfo[3],hubspotinfo[4])
				P_FlashPal(startedby, 1, 10)
				S_StartSound(startedby.mo, sfx_mixup, startedby)
				startedby.mo.angle = hubspotinfo[5]
			end
		end
	end
	
	voteinfo = {false,0,100,nil}
	playervotes = {}
	return
end

local function getsugoiinfo(t,p)
	local map = voteinfo[3]
	if t == "mapname"
		local useact = false
		local usezone = true
		if mapheaderinfo[map].actnum != 0
			useact = true
		end
		if (mapheaderinfo[map].levelflags & LF_NOZONE)
			usezone = false
		end
		if usezone == true and useact == true
			return mapheaderinfo[map].lvlttl.." ZONE "..mapheaderinfo[map].actnum
		elseif usezone == true
			return mapheaderinfo[map].lvlttl.." ZONE"
		elseif useact == true
			return mapheaderinfo[map].lvlttl.." "..mapheaderinfo[map].actnum
		else
			return mapheaderinfo[map].lvlttl
		end
	elseif t == "mappic"
		if map == finalmap
			return "EGGICON"
		else
			return G_BuildMapName(map).."P"
		end
	elseif t == "mapbeaten"
		local isboss = false
		if mapheaderinfo[map].sugoiboss
			isboss = true
		end
		if mapchecks[map] == true
			if isboss == true
				return "MAPBOSS"
			else
				return "MAPSTAR"
			end
		else
			if isboss == true
				return "MAPBOSSE"
			else
				return "MAPSTARE"
			end
		end
	elseif t == "mapdifficulty"
		if mapheaderinfo[map].sugoidifficulty == "0" // Beginner - Blue
			return SKINCOLOR_BLUE
		elseif mapheaderinfo[map].sugoidifficulty == "1" // Easy - Green
			return SKINCOLOR_GREEN
		elseif mapheaderinfo[map].sugoidifficulty == "2" // Medium - Yellow
			return SKINCOLOR_YELLOW // 2.2 Porting Note: Use SKINCOLOR_YELLOW instead since yellow isnt terrible there
		elseif mapheaderinfo[map].sugoidifficulty == "3" // Hard - Orange
			return SKINCOLOR_ORANGE
		elseif mapheaderinfo[map].sugoidifficulty == "4" // Challenging - Red
			return SKINCOLOR_RED
		else // ??? - Gray
			return SKINCOLOR_GREY
		end
	elseif t == "playervote"
		if playervotes[#p] == true
			return "You have voted \131YES\128."
		elseif playervotes[#p] == false
			return "You have voted \133NO\128."
		else
			return "You have not voted yet."
		end
	end
end

freeslot("MT_SUGOIHUBSPOT")

mobjinfo[MT_SUGOIHUBSPOT] = {
	//$Name Hub Thinker Spot
	doomednum = 2043,
	spawnstate = S_INVISIBLE,
	flags = MF_NOBLOCKMAP|MF_NOSECTOR|MF_NOGRAVITY
}

addHook("MobjThinker",function(mo)
	if voteinfo[1] == true
		for player in players.iterate do
			if (voteinfo[2] > 0 and cv_vote.value > 0)
			or (cv_vote.value == 0)
				if not (player.pflags & PF_FULLSTASIS)
					player.pflags = $1|PF_FULLSTASIS
				end
				
				local buffertime = 2
				if cv_vote.value > 0
					buffertime = (cv_vote.value * TICRATE)-10
				end
				
				if voteinfo[2] >= buffertime
				and player.cmd.buttons
					player.disablevote = true
				elseif player.disablevote == true
				and not player.cmd.buttons
					player.disablevote = false
				end
				
				if playervotes[#player] == nil
				and not player.disablevote and not player.bot
					if (player.cmd.buttons & BT_JUMP)
					and not (player.cmd.buttons & BT_SPIN)
						playervotes[#player] = true
					elseif (player.cmd.buttons & BT_SPIN)
					and not (player.cmd.buttons & BT_JUMP)
						playervotes[#player] = false
					end
				end
			end
			if (voteinfo[2] <= 0) or (getvotecount("total") >= getplayercount())
				player.pflags = $1 & !PF_FULLSTASIS
			end
		end
		
		if (voteinfo[2] <= 0) or (getvotecount("total") >= getplayercount())
			finishvote()
		end
		
		if (cv_vote.value > 0 and voteinfo[2] > 0)
		or (cv_vote.value == 0 and voteinfo[2] > 1)
			voteinfo[2] = $1 - 1
		end
	end
end, MT_SUGOIHUBSPOT)

addHook("PlayerSpawn", function(player)
	if not player.ssnumbeaten
		player.ssnumbeaten = 0
	end
	if gamemap == hubmap
		if player.lives < 3
			player.lives = 3
		end
		if player.continues < 1
			player.continues = 1
		end
	end
end)

addHook("MobjThinker", function(mo)
	if not mo.player return end
	if gamemap < finalmap
		if mo.player.exiting
			if mapchecks[gamemap] != true
				mo.player.ssnumbeaten = $1 + 1
				mapchecks[gamemap] = true
			end
			for k,v in ipairs(requirements)
				if gettotalbeaten() >= v
				and progress[k] != true
				and v != nil
					if multiplayer
					or modifiedgame
						currentCecho.text = "\""..unlocknames[k].."\" unlocked!"
						currentCecho.flags = V_YELLOWMAP|V_RETURN8
						currentCecho.timer = 6*TICRATE
					end
					progress[k] = true
				end
			end
		end
		
		if All7Emeralds(emeralds)
		and not didsbahjcecho
			if multiplayer
			or modifiedgame
				currentCecho.text = "\"Garanz Site 16\" unlocked!"
				currentCecho.flags = V_YELLOWMAP|V_RETURN8
				currentCecho.timer = 6*TICRATE
			end
			didsbahjcecho = true
		end
	end
end, MT_PLAYER)

addHook("LinedefExecute", function(line, mo, sec)
	if not voteinfo[1] == true
		voteinfo[1] = true
		if cv_vote.value > 0
			voteinfo[2] = cv_vote.value * TICRATE
		elseif cv_vote.value == 0
			voteinfo[2] = 12
		end
		voteinfo[3] = sec.tag
		voteinfo[4] = mo.player
	end
end, "VOTEEXIT")

addHook("MapLoad", function(map)
	hubspotinfo = {false,0,0,0,0}
	finishvote() // switching maps while voting is a bad idea
	
	currentCecho.text = nil
	currentCecho.flags = V_YELLOWMAP|V_RETURN8
	currentCecho.timer = 0
	
	if gamemap == hubmap
	and (multiplayer or modifiedgame or cv_emblems.value == 0)
		for i = 1,5
			if progress[i] == true
				P_LinedefExecute(mplines+i)
			end
		end
		
		if All7Emeralds(emeralds)
		or (progress[5] == true and gametype == GT_RACE)
			P_LinedefExecute(mplines+6)
		end
	else
		P_LinedefExecute(gatelines+1)
		P_LinedefExecute(gatelines+2)
		P_LinedefExecute(gatelines+3)
		P_LinedefExecute(gatelines+4)
		P_LinedefExecute(gatelines+5)
		P_LinedefExecute(gatelines+6)
		P_LinedefExecute(gatelines+9) //gatelines+7 and gatelines+8 are race-related
	end
	
	for thing in mapthings.iterate do
		if thing.valid and thing.mobj != nil
			if thing.mobj.type == MT_SUGOIBIGRING
				thing.mobj.scale = $1*2
				if (thing.options & MTF_AMBUSH)
					thing.mobj.z = $1+24*FRACUNIT
				end
			elseif thing.mobj.type == MT_SUGOIHYPERHOGAN
			and (thing.options & MTF_AMBUSH)
				thing.mobj.z = $1+24*FRACUNIT
			elseif thing.mobj.type == MT_SUGOIHUBSPOT
				hubspotinfo = {true, thing.mobj.x, thing.mobj.y, thing.mobj.z, thing.mobj.angle}
			end
		end
	end
end)

addHook("ThinkFrame", function()
	if currentCecho.timer and currentCecho.timer > 0
		currentCecho.timer = $1 - 1
	end
end)

hud.add(function(v,player)
	if voteinfo[1] == true
	and gamemap == hubmap
		local timer = voteinfo[2]
		local mapwanted = voteinfo[3]
		
		local startedname
		
		if (voteinfo[4] and voteinfo[4].valid)
			startedname = voteinfo[4].name
		elseif not startedname
			startedname = "ANIME EYES SONIC"
		end
		
		if cv_vote.value == -1 return end
		
		hud.disable("score")
		hud.disable("time")
		hud.disable("rings")
		hud.disable("lives")
		
		v.drawScaled(-1,-1,2*FRACUNIT,v.cachePatch("BLAPCK"),V_SNAPTOTOP|V_SNAPTOLEFT|V_HUDTRANSHALF) // Doesn't want to work
		v.draw(116,40,v.cachePatch("PICBACK"))
		v.drawScaled(120*FRACUNIT,43*FRACUNIT,FRACUNIT/2,v.cachePatch(getsugoiinfo("mappic")))
		v.drawScaled(192*FRACUNIT,85*FRACUNIT,FRACUNIT/2,v.cachePatch(getsugoiinfo("mapbeaten")),nil,v.getColormap(TC_DEFAULT, getsugoiinfo("mapdifficulty")))
		v.drawString(160,108,"Press [\130JUMP\128] for \131YES\128,",V_ALLOWLOWERCASE,"center")
		v.drawString(160,116,"or press [\130SPIN\128] for \133NO\128.",V_ALLOWLOWERCASE,"center")
		v.drawString(160,140,getsugoiinfo("playervote",player),V_ALLOWLOWERCASE,"center")
		if getplayercount() > 1 and multiplayer // Technically "and multiplayer" is unnecessary but Just In Case[tm]
			v.drawString(160,16,"A vote was started by \130"..startedname,V_ALLOWLOWERCASE,"center")
			v.drawString(160,24,"for \130"..getsugoiinfo("mapname").."\128.",V_ALLOWLOWERCASE,"center")
			v.drawString(16,164,"\130"..getvotecount("yes").."\128 have voted \131YES\128.",V_ALLOWLOWERCASE,"left")
			v.drawString(304,164,"\130"..getvotecount("no").."\128 have voted \133NO\128.",V_ALLOWLOWERCASE,"right")
			if cv_vote.value > 0
				v.drawString(160,188,"Voting ends in "..timer/TICRATE.." seconds",V_YELLOWMAP,"center")
			end
		else
			v.drawString(160,16,"Are you sure you want to go",V_ALLOWLOWERCASE,"center")
			v.drawString(160,24,"to \130"..getsugoiinfo("mapname").."\128?",V_ALLOWLOWERCASE,"center")
			if cv_vote.value > 0
				v.drawString(160,188,"Automatic fail in "..timer/TICRATE.." seconds",V_YELLOWMAP,"center")
			end
		end
	else
		hud.enable("score")
		hud.enable("time")
		hud.enable("rings")
		hud.enable("lives")
		
		if gamemap == hubmap
		//and (multiplayer or modifiedgame or cv_emblems.value == 0)
			if splitscreen
				if player.ssnumbeaten != nil
					v.drawString(316,90+(94*#player),""..player.ssnumbeaten,V_HUDTRANSHALF,"right")
				end
				v.drawString(316,176+(24*#player),"",V_HUDTRANSHALF,"right")
			else
				v.drawString(316,192,"welcome to GARAGE",V_HUDTRANSHALF,"right")
			end
		end
		if (currentCecho.timer and currentCecho.text and currentCecho.flags)
			v.drawString(160, 176, currentCecho.text, currentCecho.flags, "center")
		end
	end
	if gamemap == finalmap
	or gamemap == hubmap
		hud.disable("stagetitle")
	else
		hud.enable("stagetitle")
	end
end, "game")

local function drawprogressbar(vid)
	for k,v in ipairs(progress)
		local startx = 256
		local starty = 184
		local flags = V_50TRANS
		local numareas = 5
		if v == true
			flags = 0
		end
		if splitscreen
			starty = $1-8
		end
		if k == numareas
			vid.drawString(startx+(k*12),starty,"X",flags,"right")
		elseif k == numareas-1
			if All7Emeralds(emeralds)
				flags = $1|V_YELLOWMAP
			end
			vid.drawString(startx+(k*12),starty,"F",flags,"right")
		else
			vid.drawString(startx+(k*12),starty,k,flags,"right")
		end
	end
end

//hud.add(function(v)
//	if (multiplayer or modifiedgame or cv_emblems.value == 0)
//		if splitscreen
//			v.drawString(316,184,"Total beaten: "..gettotalbeaten(),0,"right")
//		else
//			v.drawString(316,192,"Maps beaten: "..gettotalbeaten(),0,"right")
//		end
//		drawprogressbar(v)
//	end
//end, "scores")

// "50" BIG RING OBJECT
// Replacement for emerald tokens (that weren't turned into actual chaos emeralds)
freeslot("MT_SUGOIBIGRING", "S_SUGOIBIGRING", "S_BIGRING50", "SPR_BR50")

mobjinfo[MT_SUGOIBIGRING] = {
	//$Sprite RINGA0
	//$Name Big Ring
	doomednum = 2040,
	spawnstate = S_SUGOIBIGRING,
	deathstate = S_SPRK1,
	deathsound = sfx_itemup,
	speed = 38*FRACUNIT,
	radius = 16*FRACUNIT,
	height = 32*FRACUNIT,
	flags = MF_SLIDEME|MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT
}

states[S_SUGOIBIGRING] = {SPR_RING, A|FF_ANIMATE, -1, nil, 23, 1, S_SUGOIBIGRING}
states[S_BIGRING50] = {SPR_BR50, A, 1, nil, 0, 12, S_NULL}

addHook("MobjSpawn", function(mo)
	if not (G_PlatformGametype())
		mo.fuse = 1
	end
end, MT_SUGOIBIGRING)

addHook("MobjDeath", function(mo,no,pmo)
	if pmo and pmo.valid
	and pmo.player != nil
		P_GivePlayerRings(pmo.player, 50)
	end
end, MT_SUGOIBIGRING)

/*addHook("MobjThinker", function(mo)
	local fifty = P_SpawnMobj(mo.x, mo.y, mo.z, MT_OVERLAY)
	fifty.target = mo
	fifty.state = S_BIGRING50
	if fifty.valid
		if mo.state == S_SPRK1 or mo.state == S_SPRK2
		or mo.state == S_SPRK3 or mo.state == S_SPRK4
			P_RemoveMobj(fifty)
		end
	end
end, MT_SUGOIBIGRING)*/

// HYPER HOGAN HEAD
// Unlocks Area X
freeslot("MT_SUGOIHYPERHOGAN", "S_SUGOIHYPERHOGAN", "SPR_HHGN")

mobjinfo[MT_SUGOIHYPERHOGAN] = {
	//$Sprite HHGNA0
	//$Name Hyper Hogan Head
	doomednum = 2041,
	spawnstate = S_SUGOIHYPERHOGAN,
	deathstate = S_SPRK1,
	deathsound = sfx_token,
	radius = 21*FRACUNIT,
	height = 42*FRACUNIT,
	flags = MF_SPECIAL|MF_NOGRAVITY|MF_NOCLIPHEIGHT
}

states[S_SUGOIHYPERHOGAN] = {SPR_HHGN, A|FF_ANIMATE, -1, nil, 9, 2, S_SUGOIHYPERHOGAN}

addHook("MobjSpawn", function(mo)
	if progress[5] == true or modeattacking
		mo.fuse = 1
	end
end, MT_SUGOIHYPERHOGAN)

addHook("MobjDeath", function(mo,no,pmo)
	if progress[5] != true
		if multiplayer or modifiedgame
			currentCecho.text = "\""..unlocknames[5].."\" unlocked!"
			currentCecho.flags = V_YELLOWMAP|V_RETURN8
			currentCecho.timer = 6*TICRATE
		end
		if pmo and pmo.valid
			P_LinedefExecute(hogantag, pmo) // i wish i could just set condition set triggers via lua without a linedef executor...
		else
			P_LinedefExecute(hogantag)
		end
		progress[5] = true
	end
end, MT_SUGOIHYPERHOGAN)

// TINY TOILET
// Because toilet humor.
freeslot("MT_SUGOITOILET", "S_SUGOITOILET", "SPR_TOIL")

mobjinfo[MT_SUGOITOILET] = {
	//$Sprite TOILA0
	//$Name Tiny Toilet
	doomednum = 2042,
	spawnstate = S_SUGOITOILET,
	radius = 9*FRACUNIT,
	height = 27*FRACUNIT,
	flags = MF_SOLID
}

states[S_SUGOITOILET] = {SPR_TOIL, A, -1, nil, 0, 0, S_SUGOITOILET}
