require("class")
require("map/map")

require("screens/testscreen")

-- TODO: teleporting; wormholes; fix IsKeyBinding

-- Use OpenMenu (commands.lua) for console command
function ToggleMenu()
	if not GetPlayer().components.testtoolcontroller then
		print("Missing TTC component.")
		return
	end

	local active_screen = TheFrontEnd:GetActiveScreen()
	
	if active_screen and active_screen.displayed then
		active_screen:Close()
		return
	end
	
	if not IsHUDPaused() then
		SetHUDPause(true)
		TheFrontEnd:PushScreen(TestScreen(true))
	end
end

local function IsValidTile(point)
	local ground = TheSim:FindFirstEntityWithTag("ground")
	
	if ground and point then
		local tile = ground.Map:GetTileAtPoint(point.x, point.y, point.z)
		if tile ~= GROUND.IMPASSIBLE then
			return true
		end
	end	

	return false
end

--[[
	New function IsKeyBinding to test if currently pressed keys match desired key binding
	Created by: WrathOf
--]]
local function IsKeyBinding(key, modifiers)
	if TheInput:IsKeyDown(key) then
		if modifiers then
			for k,v in ipairs(modifiers) do
				if not TheInput:IsKeyDown(v) then return false end
			end
			return true
		else
			return not ( TheInput:IsKeyDown(KEY_CTRL) or TheInput:IsKeyDown(KEY_SHIFT) or TheInput:IsKeyDown(KEY_ALT) )
		end
	else
	  return false
	end
end

-- \ key code missing from constants.lua
KEY_BACKSLASH = 92

local TestToolController = Class(function(self, inst)

	self.inst = inst

	self.entityPrefab = nil
	self.itemPrefab = nil
	self.foodPrefab = nil
	self.objectPrefab = nil

	self.speed_multiplier = nil

	self.bookmarked_point = nil

	self.inputhandlers = {}

  -- Menu key #1
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_F1, function()
		ToggleMenu()
	end))
	
	-- Menu key #2
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_BACKSLASH, function()
		ToggleMenu()
	end))
	
	-- God mode
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_G, function()
		if IsKeyBinding(KEY_G, {KEY_CTRL}) then
			ToggleGodMode()
		end
	end))
	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_Z, function()
		-- Change season
		if IsKeyBinding(KEY_Z, {KEY_CTRL}) then
			NextSeason()
		-- Spawn entity (mouse)
		elseif IsKeyBinding(KEY_Z, {KEY_SHIFT}) then 
			Spawn(self.entityPrefab) 
		end
	end))
  	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_X, function()
		-- Spawn item (inventory)
		if IsKeyBinding(KEY_X, {KEY_CTRL}) then
			SpawnInv(self.itemPrefab)
		-- Spawn item (mouse)
		elseif IsKeyBinding(KEY_X, {KEY_SHIFT}) then
			Spawn(self.itemPrefab) 
		end
	end))
  	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_C, function()
		-- Freebuild
		if IsKeyBinding(KEY_C, {KEY_CTRL}) then
			Freebuild()
		-- Change characters
		elseif IsKeyBinding(KEY_C, {KEY_SHIFT}) then
			if not IsHUDPaused() then
				CharacterSelect()
			end
		end
	end))
	
	-- Time scale
  	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_V, function()
		if IsKeyBinding(KEY_V, {KEY_CTRL}) then
			ToggleTimeScale()
		end
	end))
	
	-- Next day
  	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_F, function()
		if IsKeyBinding(KEY_F, {KEY_SHIFT}) then
			NextDay()
		end
	end))
	
	-- Next phase
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_G, function()
		if IsKeyBinding(KEY_G, {KEY_SHIFT}) then
			NextPhase()
		end
	end))
	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_T, function()
		-- Food (inventory)
		if IsKeyBinding(KEY_T, {KEY_CTRL}) then
			SpawnInv(self.foodPrefab)
		-- Food (mouse)
		elseif IsKeyBinding(KEY_T, {KEY_SHIFT}) then
			Spawn(self.foodPrefab)
		-- Map hide
		elseif IsKeyBinding(KEY_T, {KEY_ALT}) then
			MapHide()
		end
	end)) 

  	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_R, function()
		-- Run speed
		if IsKeyBinding(KEY_R, {KEY_CTRL}) then
			ToggleSpeed(self.speed_multiplier)
		-- Object (mouse)
		elseif IsKeyBinding(KEY_R, {KEY_SHIFT}) then
			Spawn(self.objectPrefab)
		-- Map reveal
		elseif IsKeyBinding(KEY_R, {KEY_ALT}) then
			MapReveal()
		end
	end))
	
	table.insert(self.inputhandlers, TheInput:AddMouseButtonHandler(MOUSEBUTTON_LEFT, true, function()
		-- Teleport player (mouse)
		if (TheInput:IsKeyDown(KEY_CTRL) and TheInput:IsKeyDown(KEY_SHIFT)) then
			local pt = TheInput:GetMouseWorldPos()
				
			if IsValidTile(pt) then
				self.inst.Physics:Teleport(pt.x, pt.y, pt.z)
			end
		end
	end))
	
	table.insert(self.inputhandlers, TheInput:AddMouseButtonHandler(MOUSEBUTTON_RIGHT, true, function()
		-- Bookmark point
		if TheInput:IsKeyDown(KEY_CTRL) then
			self.bookmarked_point = Vector3(self.inst.Transform:GetWorldPosition())
		-- Teleport player (bookmark)
		elseif TheInput:IsKeyDown(KEY_SHIFT) then
			local pt = self.bookmarked_point
			
			if IsValidTile(pt) then
				self.inst.Physics:Teleport(pt.x, pt.y, pt.z)
			end	
		end
	end))	
	
	-- Delete (mouse)
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_B, function()
		if IsKeyBinding(KEY_B, {KEY_SHIFT}) then	
			local target = TheInput:GetWorldEntityUnderMouse()
			
			if target and not target:HasTag("player") then
				if target.components.crop then
					target.components.crop:Mature()
					target.components.crop:Harvest(self.inst)
				end

				target:Remove()
			end	
		end

  end))
  
	-- Rain
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_I, function()
		if IsKeyBinding(KEY_I, {KEY_CTRL}) then
			ToggleRain()
		end
	end))
  
  self.inst:StartUpdatingComponent(self)
end)

-- Remove handlers if player changes character
function TestToolController:OnRemoveEntity()
    for k,v in pairs(self.inputhandlers) do
        v:Remove()
    end
end

return TestToolController