--[[
	Scripted by Toxicity.
	27.01.2020
]]

import(Module_Defines);
import(Module_DataTypes);
import(Module_MapWho);
import(Module_Person);
import(Module_Helpers);
import(Module_System);
import(Module_Game);
import(Module_Objects);
import(Module_Globals);
import(Module_Map);
import(Module_Level);
import(Module_String);
import(Module_Table);
import(Module_Math);
import(Module_Players);
import(Module_PopScript);
import(Module_ImGui);
import (Module_Draw);

log_msg(TRIBE_NEUTRAL, "Press 'CAPS LOCK' to toggle the Statistics window.")
local MAX_POINTS = 5;
local BANK_CLASSIC 	= 1; -- 0, 1
local BANK_NORMAL 	= 5; -- 4, 5
local BANK_HARD 	= 3; -- 2, 3
local TIMER_RESET = -1;
local _gnsi = gnsi();
local _gsi = gsi();
local g_DrawMenu = false;
local g_Turn = 0;
local g_TurnBegin = _gsi.Counts.GameTurn;
local g_TurnEnd = 0;
local g_Exit = false;
local g_Winner = TRIBE_NEUTRAL;
local g_ArenaCenter = MapPosXZ.new();
g_ArenaCenter.XZ.X = 28;
g_ArenaCenter.XZ.Z = 78;
--_gnsi.GameParams.Flags2 = _gnsi.GameParams.Flags2 | GPF2_GAME_NO_WIN;
local g_Init = false;

-- Index starting at 1
local g_SpawnPositions =
{
	MAP_XZ_2_WORLD_XYZ(42, 64),
	MAP_XZ_2_WORLD_XYZ(28, 64),
	MAP_XZ_2_WORLD_XYZ(14, 64),
	MAP_XZ_2_WORLD_XYZ(42, 78),
	MAP_XZ_2_WORLD_XYZ(14, 78),
	MAP_XZ_2_WORLD_XYZ(42, 92),
	MAP_XZ_2_WORLD_XYZ(28, 92),
	MAP_XZ_2_WORLD_XYZ(14, 92)
}
local g_ShamansAlive = { false, false, false, false, false, false, false, false };
local g_Points = { 0, 0, 0, 0, 0, 0, 0, 0 };
local g_PlayerNames = { "Blue",	"Red", "Yellow", "Green", "Cyan", "Pink", "Black", "Orange" };
local g_Manager = nil;

CRoundManager = {};
CRoundManager.new = function(_Countdown)
    local m = {};

	m.TurnStart = 0;
    m.Started = false; -- Starts the countdown
    m.Timer = _Countdown;
	m.BlastTimer = TIMER_RESET;
	m.BankTimer = TIMER_RESET;
	m.Bank = 1;
	m.NumOfShamans = 0;
	m.Winner = -1;
	m.Ended = false;

	function m.ShowCheckRadius(me)
		local c3d = Coord3D.new();
		map_idx_to_world_coord3d(MAP_ELEM_PTR_2_IDX(me), c3d);
		createThing(T_EFFECT, M_EFFECT_SMOKE, TRIBE_HOSTBOT, c3d, false, false);
	end

	function m.RoundStarted()
		return m.Started;
	end

	function m.RoundEnded()
		return m.Ended;
	end

	function m.StartRound(turn)
		for pn=0,MAX_NUM_REAL_PLAYERS-1,1 do
			_gsi.ThisLevelInfo.PlayerThings[pn].SpellsAvailable = 0;
			for i=0,NUM_SPELL_TYPES,1 do
				_gsi.ThisLevelInfo.PlayerThings[pn].SpellsAvailableOnce[i] = 0;
			end
		end
		m.Started = true;
		m.TurnStart = turn;
	end

	function m.EndRound()
		log_msg(TRIBE_NEUTRAL, "Player [" .. tostring(m.Winner) .. "] won this round! (+1 Point)");
		g_Points[m.Winner+1] = g_Points[m.Winner+1] + 1;

		if (g_Points[m.Winner+1] == MAX_POINTS) then
			log_msg(TRIBE_NEUTRAL, "Player [" .. tostring(m.Winner) .. "]" .. " is victorious!");

			--_gnsi.GameParams.Flags2 = _gnsi.GameParams.Flags2 ~ GPF2_GAME_NO_WIN;

			for pn=0,MAX_NUM_REAL_PLAYERS-1,1 do
				if (pn ~= m.Winner) then
					getPlayer(pn).ShamanLives = 0;
					destroy_reinc(getPlayer(pn));
					if (getShaman(pn) ~= nil) then
						damage_person(getShaman(pn), TRIBE_HOSTBOT, 9999, FALSE);
					end
				end
			end

			createThing(T_SPELL, M_SPELL_VOLCANO, m.Winner, getShaman(m.Winner).Pos.D3, false, false);
			g_Exit = true;
			g_Winner = m.Winner;
		else
			SearchMapCells(CIRCULAR, 0, 0, 13, g_ArenaCenter.Pos, function(me)
				me.MapWhoList:processList(function(t)
					if (t.Type == T_PERSON and t.Model == M_PERSON_MEDICINE_MAN) then
						damage_person(t, TRIBE_HOSTBOT, 9999, FALSE);
					end
				return true;
				end);
			return true;
			end);

			_gsi.ThisLevelInfo.PlayerThings[m.Winner].SpellsAvailable = 0;
			for i=0,NUM_SPELL_TYPES,1 do
				_gsi.ThisLevelInfo.PlayerThings[m.Winner].SpellsAvailableOnce[i] = 0;
			end
		end

		m.setBank(BANK_CLASSIC);
		m.Ended = true;
	end

	function m.CheckForRound()
	    if (m.Started == false) then
	        local start = true;
	        SearchMapCells(CIRCULAR, 0, 0, 13, g_ArenaCenter.Pos, function(me)
	            --m.ShowCheckRadius(me);
	            me.MapWhoList:processList(function(t)
	                if (t.Type == T_PERSON and t.Model == M_PERSON_MEDICINE_MAN) then
	                	start = false;
	            	end
	            return true;
	        	end);
	        return true;
	    	end);
	    	return start;
	    end
	    return false;
	end

	function m.setBank(bank)
		if (m.Bank ~= bank) then
			-- TODO, reenable these
			change_sprite_bank(0, bank - 1);
			change_sprite_bank(1, bank);
			m.Bank = bank;
			log_msg(TRIBE_NEUTRAL, "Using bank.. " .. tostring(bank - 1) .. " and " .. tostring(bank))
		end
	end

	function m.ProcessRound(turn)
		turn = (turn - m.TurnStart);

		-- Logging system messages
		if (m.Timer >= 0) then
			if (m.Timer == _Countdown) then
				log_msg(TRIBE_NEUTRAL, "Round is about to begin!");
			elseif (m.Timer > 0) then
				log_msg(TRIBE_NEUTRAL, tostring(m.Timer))
			elseif (m.Timer == 0) then
				log_msg(TRIBE_NEUTRAL, "START!");
				for pn=1,#g_SpawnPositions do
					createThing(T_EFFECT, M_EFFECT_TELEPORT, pn-1, g_SpawnPositions[pn], false, false)
				end
			end
			m.Timer = m.Timer - 1;
		end

		-- Give everyone a Blast shot
		if (m.BlastTimer == 3) then
			for pn=0,MAX_NUM_REAL_PLAYERS-1,1 do
				GIVE_ONE_SHOT(M_SPELL_BLAST, pn);
				m.BlastTimer = TIMER_RESET;
			end
		end

		for pn=1,#g_ShamansAlive do
			g_ShamansAlive[pn] = false;
		end

		-- Check for Shamans inside the arena
		local numOfShamans = 0;
		SearchMapCells(SQUARE, 0, 0, 13, g_ArenaCenter.Pos, function(me)
			--m.ShowCheckRadius(me);
			me.MapWhoList:processList(function(t)
				if (t.Type == T_PERSON and t.Model == M_PERSON_MEDICINE_MAN) then
					numOfShamans = numOfShamans + 1;
					g_ShamansAlive[t.Owner + 1] = true;
					m.Winner = t.Owner;
				end
			return true;
			end);
		return true;
		end);

		-- Dead players should have no spell shots
		for pn=1,#g_ShamansAlive do
			if (g_ShamansAlive[pn] == false) then
				_gsi.ThisLevelInfo.PlayerThings[pn-1].SpellsAvailable = 0;
				for i=0,NUM_SPELL_TYPES,1 do
					_gsi.ThisLevelInfo.PlayerThings[pn-1].SpellsAvailableOnce[i] = 0;
				end
			end
		end

		if (m.NumOfShamans ~= numOfShamans) then
			m.NumOfShamans = numOfShamans;
			m.BankTimer = TIMER_RESET;
		end

		if (numOfShamans <= 1 and m.Winner ~= -1) then
			if (m.Ended == false) then
				m.EndRound();
				g_TurnEnd = turn;
			end
		else
			if (numOfShamans == 2) then
				m.setBank(BANK_HARD);
			elseif (numOfShamans <= 4) then
				if (m.BankTimer >= 0 and m.BankTimer <= 5) then
					m.setBank(BANK_CLASSIC)
				elseif (m.BankTimer >= 6 and m.BankTimer <= 7) then
					m.setBank(BANK_NORMAL)
				else
					m.BankTimer = TIMER_RESET;
				end
			else
				if (m.BankTimer >= 0 and m.BankTimer <= 10) then
					m.setBank(BANK_CLASSIC)
				elseif (m.BankTimer >= 11 and m.BankTimer <= 12) then
					m.setBank(BANK_NORMAL)
				else
					m.BankTimer = TIMER_RESET;
				end
			end

			m.BlastTimer = m.BlastTimer + 1;
			m.BankTimer = m.BankTimer + 1;
		end
	end

	return m;
end

function OnTurn()
	g_Turn = ((_gsi.Counts.GameTurn - g_TurnBegin) / 12);

	if (g_Turn == 0) then
		return;
	end

	if (g_Init == false) then
		for pn=0,MAX_NUM_REAL_PLAYERS-1,1 do
			local shaman = getShaman(pn);
			if (shaman ~= nil) then
				getPlayer(pn).ShamanLives = 99;
			end
		end
		g_Init = true;
	end

	if (g_Exit == false) then
		if (g_Manager == nil) then
			g_Manager = CRoundManager.new(6);
		end

		if (g_Manager.RoundEnded() == true) then
			g_Manager = nil;
		else
			if (g_Manager.RoundStarted() == false) then
				if ((g_Turn % 5) == 0) then
					if (g_Manager.CheckForRound() == true) then
						g_Manager.StartRound(g_Turn);
					end
				end
			else
				if ((g_Turn % 1) == 0) then
					g_Manager.ProcessRound(g_Turn);
				end
			end
		end
	else
		if (g_Turn % 1) then
			if (g_Turn > (g_TurnEnd + 3)) then
				ProcessGlobalTypeList(T_PERSON, function(t)
					if (t.Owner ~= g_Winner) then
						damage_person(t, TRIBE_HOSTBOT, 9999, FALSE);
					end
					return true
				end)
			end
		end
	end
end

function OnKeyDown(key)
    if (key == LB_KEY_CAPS) then
        g_DrawMenu = not g_DrawMenu;
    end
	
	
	
	
	function OnKeyDown(key)
    if (key == LB_KEY_CAPS) then
        g_DrawMenu = not g_DrawMenu;
    end


    if (key == LB_KEY_1) then
        change_sprite_bank(0, 1);
    end

    if (key == LB_KEY_2) then
        change_sprite_bank(0, 0);
    end

    if (key == LB_KEY_3) then
        change_sprite_bank(1, 1);
    end

    if (key == LB_KEY_4) then
        change_sprite_bank(0, 2);
    end

    if (key == LB_KEY_5) then
        change_sprite_bank(0, 0);
    end
    --[[
    if (key == LB_KEY_1) then
        for i=0,MAX_NUM_REAL_PLAYERS-1,1 do
            if (i ~= 0) then
                local shaman = getShaman(i);
                if (shaman ~= nil) then
                    damage_person(shaman, TRIBE_HOSTBOT, 9999, FALSE);
                end
            end
        end
    end
    ]]
end

	--[[
	if (key == LB_KEY_1) then
		for i=0,MAX_NUM_REAL_PLAYERS-1,1 do
			if (i ~= 0) then
				local shaman = getShaman(i);
				if (shaman ~= nil) then
					damage_person(shaman, TRIBE_HOSTBOT, 9999, FALSE);
				end
			end
		end
	end
	]]
end

function OnImGuiFrame()
    if (g_DrawMenu) then
        imgui.Begin('Statistics', nil, ImGuiWindowFlags_AlwaysAutoResize);

		imgui.Columns(3, "Stats");
	   	imgui.TextUnformatted("Player");
	   	imgui.NextColumn();
		imgui.TextUnformatted("Playing");
		imgui.NextColumn();
	   	imgui.TextUnformatted("Points");
		imgui.Separator();
		imgui.NextColumn();

		for pn=0,MAX_NUM_REAL_PLAYERS-1,1 do
			imgui.TextUnformatted(g_PlayerNames[pn+1] .. " [" .. tostring(pn+1) .. "]");
			imgui.NextColumn();
			imgui.TextUnformatted(tostring(g_ShamansAlive[pn+1]));
			imgui.NextColumn();
			imgui.TextUnformatted(tostring(g_Points[pn+1]) .. "/" .. tostring(MAX_POINTS));
			imgui.NextColumn();
		end

        imgui.End();
    end
end
