require "class"
require "screens/pausescreen"
local easing = require "easing"

local trace = function() end

local CLICK_WALK_TIME = .5

local prefabs =
{
    "bishop_charge","monstermeat","beemine_maxwell","shovel","spidergland","flint","ash","torch","tentaclespike","log","nitre","silk","poop","campfire","pinecone"
}

local CameraRight = TheCamera:GetRightVec()
local CameraDown = TheCamera:GetDownVec()

local function UpdateCameraHeadings()
	CameraRight = TheCamera:GetRightVec()
	CameraDown = TheCamera:GetDownVec()
end

local PlayerController_2 = Class(function(self, inst)
    self.inst = inst
    self.enabled = true
    
    
    self.inputhandlers = {}

    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_G, function() self:AON() end))
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_Y, function() self:Pick() end))
	
----------    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_O, function() self:ToolUseaxe() end))
	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_V, function() self:beemine_2() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_L, function() self:CraftTrap() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_I, function() self:DropAll() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_M, function() self:CraftRabbitHeal() end))
------  table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_B, function() inst.components.container:Close(inst) end))
------  table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_N, function() self:Craftspike() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_F, function() self:Craftfire() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_O, function() self:TP() end))
    table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_N, function() self:ChopTree() end))
-----KEY_LESS  GREATER   ChopTree

	
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_P, function() self:SpawnPlayer2() end))
	table.insert(self.inputhandlers, TheInput:AddKeyDownHandler(KEY_RIGHTBRACKET, function() self:adv_portal() end))

    self.inst:StartUpdatingComponent(self)
    self.draggingonground = false
    self.startdragtestpos = nil
    self.startdragtime = nil
end)



function PlayerController_2:SpawnPlayer2()
    self.inst.components.health:DoDelta(-10000)
end

---local
local function SpawnEffect(inst)
    local pt = inst:GetPosition()
    local fx = SpawnPrefab("small_puff")
    fx.Transform:SetPosition(pt.x, pt.y, pt.z)
    fx.Transform:SetScale(0.5,0.5,0.5)
end

local function SpawnEffect2(inst)
    local pt = inst:GetPosition()
    local fx = SpawnPrefab("small_puff")
    fx.Transform:SetPosition(pt.x, pt.y, pt.z)
    fx.Transform:SetScale(0.9,0.9,0.9)
end


local function getitem(self, item)
    --Amulet will only ever pick up items one at a time. Even from stacks.
    if item.components.stackable then
        item = item.components.stackable:Get()
    end
	SpawnEffect(item)

    self.inst.components.container:GiveItem(item)
end


----local end

function PlayerController_2:TPpoint(pt)
    local theta = math.random() * 2 * PI
    local radius = 6

	local offset = FindWalkableOffset(pt, theta, radius, 12, true)
	if offset then
		return pt+offset
	end
end

function PlayerController_2:TP()
	local player = GetPlayer()
	local tp = self.inst
	
	local pt = Vector3(GetPlayer().Transform:GetWorldPosition())
	
	if (tp:GetDistanceSqToInst(player) > (10*10)) then
		local spawn_pt = self:TPpoint(pt)
		
		tp.AnimState:PlayAnimation("dissipate")
		
		self.inst:DoTaskInTime(0.7, function() 
			tp.Physics:Teleport(spawn_pt:Get())			
			tp.sg:GoToState("appear")
		end)
	end
end

function PlayerController_2:Open()
    self.inst.components.container:Open(self)
end
function PlayerController_2:Close()
    self.inst.components.container:Close(self)
end



-------------------------------------------------------------------------------------
----------------------------   CRAFT
-------------------------------------------------------------------------------------




function PlayerController_2:CraftRabbitHeal()
    if self.inst.components.container:Has("monstermeat", 1) then
    local rabbit = SpawnPrefab("rabbit")
    rabbit.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
    self.inst.components.container:ConsumeByName("monstermeat", 1)
	self.inst.components.aura.radius = 0
	SpawnEffect2(rabbit)
    local rabbit = SpawnPrefab("spidergland")
    rabbit.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
	end
end

function PlayerController_2:Craftspike()
    if self.inst.components.container:Has("ash", 4) and self.inst.components.container:Has("torch", 1) then
    local rabbit = SpawnPrefab("tentaclespike")
    rabbit.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
    self.inst.components.container:ConsumeByName("ash", 4)
    self.inst.components.container:ConsumeByName("torch", 1)
	self.inst.components.aura.radius = 0
	SpawnEffect2(rabbit)
end
end


function PlayerController_2:Craftfire()
    if self.inst.components.container:Has("pinecone", 2) then
    local rabbit = SpawnPrefab("campfire")
    rabbit.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
    self.inst.components.container:ConsumeByName("pinecone", 2)
	self.inst.components.aura.radius = 0
end
end


function PlayerController_2:CraftTrap()
    if self.inst.components.container:Has("spidergland", 1)or self.inst.components.container:Has("flint", 1) or self.inst.components.container:Has("twigs", 1) then
	local bishop_charge = SpawnPrefab("trap_teeth_maxwell")

	if self.inst.components.container:Has("spidergland", 1) then
    self.inst.components.container:ConsumeByName("spidergland", 1)
	elseif self.inst.components.container:Has("flint", 1) then
    self.inst.components.container:ConsumeByName("flint", 1)
	elseif self.inst.components.container:Has("twigs", 1) then
    self.inst.components.container:ConsumeByName("twigs", 1)
	end
	
	
	bishop_charge.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
	self.inst.components.aura.radius = 0
	SpawnEffect2(bishop_charge)
    local light = bishop_charge.entity:AddLight()
    light:SetIntensity(.4)
    light:SetRadius(.4)
    light:SetFalloff(.3)
    light:Enable(true)
    light:SetColour(1/255, 1/255, 255/255)
	end
end


function PlayerController_2:beemine_2()
    if self.inst.components.container:Has("spidergland", 1)or self.inst.components.container:Has("flint", 1) or self.inst.components.container:Has("twigs", 1) then
	local bishop_charge = SpawnPrefab("beemine_maxwell")
	
	if self.inst.components.container:Has("spidergland", 1) then
    self.inst.components.container:ConsumeByName("spidergland", 1)
	elseif self.inst.components.container:Has("flint", 1) then
    self.inst.components.container:ConsumeByName("flint", 1)
	elseif self.inst.components.container:Has("twigs", 1) then
    self.inst.components.container:ConsumeByName("twigs", 1)
	end
	
    bishop_charge.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
	SpawnEffect2(bishop_charge)
    local light = bishop_charge.entity:AddLight()
    light:SetIntensity(.3)
    light:SetRadius(.4)
    light:SetFalloff(.3)
    light:Enable(true)
    light:SetColour(255/255, 1/255, 1/255)
	self.inst.components.aura.radius = 0
end
end



-------------------------------------------------------------------------------------
----------------------------   CRAFT END
-------------------------------------------------------------------------------------



-------------------------------------------------------------------------------------
--------------------------- CHOP IT DOWN!!!!!
-------------------------------------------------------------------------------------

function PlayerController_2:ChopTree()
	self.inst.components.aura.radius = 0
  if self.inst.components.container:Has("axe", 1) and self.inst.components.hunger.current > 70 then
   
		local targ = FindEntity(self.inst, 4, function(guy) return (guy.components.workable and guy.components.workable.action == ACTIONS.CHOP and guy.components.burnable) end)

		if targ then
    targ:RemoveComponent("burnable")
   self.inst.components.hunger:DoDelta(-10*targ.components.growable.stage)
    local pt = Vector3(targ.Transform:GetWorldPosition())
    local hispos = Vector3(targ.Transform:GetWorldPosition())
	
    targ:AddComponent("health")
    targ.components.health:SetMaxHealth(5)
    targ.components.health:StartRegen(-5, 1)
    targ.AnimState:PlayAnimation(targ.anims.chop)
    targ.AnimState:PushAnimation(targ.anims.sway1, true)
	
    local he_right = (hispos - pt):Dot(TheCamera:GetRightVec()) > 0
    
    if he_right then
        targ.AnimState:PlayAnimation(targ.anims.fallleft)
        targ.components.lootdropper:DropLoot(pt - TheCamera:GetRightVec())
    else
        targ.AnimState:PlayAnimation(targ.anims.fallright)
        targ.components.lootdropper:DropLoot(pt + TheCamera:GetRightVec())
    end

    targ:DoTaskInTime(.4, function() 
		local sz = (targ.components.growable and targ.components.growable.stage > 2) and .5 or .25
		GetPlayer().components.playercontroller:ShakeCamera(targ, "FULL", 0.25, 0.03, sz, 6)
    targ:DoTaskInTime(.4, function() 
	SpawnEffect2(targ)
	targ:Remove()
    end)
		end)
end
end
end


-------------------------------------------------------------------------------------
--------------------------- CHOP IT DOWN END
-------------------------------------------------------------------------------------



function PlayerController_2:OnRemoveEntity()
    for k,v in pairs(self.inputhandlers) do
        v:Remove()
    end
end


function PlayerController_2:Enable(val)
    self.enabled = val
end


function PlayerController_2:adv_portal()
	local bishop_charge = SpawnPrefab("adventure_portal")
    bishop_charge.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
    bishop_charge:AddComponent("health")
    bishop_charge.components.health:SetMaxHealth(30)
    bishop_charge.components.health:StartRegen(-31, 10)
end





function PlayerController_2:AON()
    self.inst.components.aura.radius = 4
	local bishop_charge = SpawnPrefab("bishop_charge")
    bishop_charge.Transform:SetPosition(self.inst.Transform:GetWorldPosition())
	
   if self.inst.components.health.currenthealth < 100 then
   self.inst.AnimState:SetMultColour(0.7,0.1,0.1,0.2)
	elseif self.inst.components.health.currenthealth > 101 then
    local i = self.inst.components.health.currenthealth/325
	local d = i*0.7
    local r = 1-(i*1.3)
    self.inst.AnimState:SetMultColour(i,d,d,r)

   end
end





function PlayerController_2:DropAll()
	self.inst.components.container:DropEverything()
end



---ORANGE



function PlayerController_2:Pick()
    local pt = self.inst:GetPosition()
    local ents = TheSim:FindEntities(pt.x, pt.y, pt.z, TUNING.ORANGEAMULET_RANGE+1)

    for k,v in pairs(ents) do
        if v.components.inventoryitem and v.components.inventoryitem.canbepickedup and v.components.inventoryitem.cangoincontainer and not
            v.components.inventoryitem:IsHeld() then

            if not self.inst.components.container:IsFull() then
                --Your container isn't full, you can pick something up.
                getitem(self, v)
                return

            elseif v.components.stackable then
                --Your container is full, but the item you're trying to pick up stacks. Check for an exsisting stack.
                --An acceptable stack should: Be of the same item type, not be full already and not be in the "active item" slot of container .
                local stack = self.inst.components.container:FindItem(function(item) return (item.prefab == v.prefab and not item.components.stackable:IsFull()
                    and item ~= self.inst.components.container.activeitem) end)
                if stack then
                    getitem(self, v)
                    return
                end
            end
        end
    end
   if self.inst.components.hunger.current < 70 then
   self.inst.AnimState:SetMultColour(1,0.1,0.1,.4)
   end
   if self.inst.components.hunger.current < 10 then
   self.inst.AnimState:SetMultColour(0.1,0.1,0.1,.4)
   self.inst.components.hunger:DoDelta(10)
   self.inst.components.health:DoDelta(-85)
   end
end




function PlayerController_2:OnUpdate(dt)
    if self.inst.components.health.currenthealth <= 0 then
	self.inst.components.container:DropEverything()
	end


	if not self.inst.sg:HasStateTag("busy") then
		if self.startdragtime then
			local pt = TheInput:GetMouseWorldPos()
			local dst = distsq(pt, Vector3(self.inst.Transform:GetWorldPosition()))
			if dst > 1 then
				local angle = self.inst:GetAngleToPoint(pt)
				--self.inst.components.locomotor:GoToPoint(pt, nil, true)
				self.inst.components.locomotor:RunInDirection(angle)
				self.inst:ClearBufferedAction()
				TheInput:DisableMouseovers()            
			end
			self.directwalking = false
		else
	        
			--WASD walking!
			local xwalk = 0
			local ywalk = 0
			if TheInput:IsKeyDown(KEY_U) then
				ywalk = ywalk + 1
			end

			if TheInput:IsKeyDown(KEY_J) then
				ywalk = ywalk - 1
			end

			if TheInput:IsKeyDown(KEY_H) then
				xwalk = xwalk - 1
			end
	        
			if TheInput:IsKeyDown(KEY_K) then
				xwalk = xwalk + 1
			end
	        
			if not 	TheInput:IsKeyDown(KEY_U) and not --We only want to update headings if no keys are pressed.
					TheInput:IsKeyDown(KEY_H) and not
					TheInput:IsKeyDown(KEY_J) and not
					TheInput:IsKeyDown(KEY_K) then

					
					CameraRight = TheCamera:GetRightVec()
					CameraDown = TheCamera:GetDownVec()
			end
			
			if xwalk ~= 0 or ywalk ~= 0 then
				--self.inst.components.inventory:DropActiveItem()

     			local dir = CameraRight * xwalk - CameraDown * ywalk
				dir = dir:GetNormalized()
				--local pt = Vector3(self.inst.Transform:GetWorldPosition()) + dir
				--self.inst.components.locomotor:GoToPoint(pt, nil, true)
				local ang = -math.atan2(dir.z, dir.x)/DEGREES
				self.inst.components.locomotor:WalkInDirection(ang, true)
				self.directwalking = true
				self.inst.components.locomotor:SetBufferedAction(nil)
				self.inst:ClearBufferedAction()
				
				if not self.inst.sg:HasStateTag("attack") then
					self.inst.components.combat:SetTarget(nil)
				end
			else
				if self.directwalking then
					self.inst.components.locomotor:Stop()
					self.directwalking = false
				end
            end
		end
    end
    
end




function PlayerController_2:DoAction(buffaction)
	Print(VERBOSITY.DEBUG, "PlayerController_2:DoAction")
    if buffaction then
    
        if self.inst.bufferedaction then
            if self.inst.bufferedaction.action == buffaction.action and self.inst.bufferedaction.target == buffaction.target then
                return;
            end
        end
        
        if buffaction.target and buffaction.target.components.highlight then
            buffaction.target.components.highlight:Flash(.2, .125, .1)
        end
		
		Print(VERBOSITY.DEBUG, "Performing Action: ["..buffaction.action.id.."]")
        if  buffaction.invobject and 
            buffaction.invobject.components.equippable and 
            buffaction.invobject.components.equippable.equipslot == EQUIPSLOTS.HANDS and 
            (buffaction.action ~= ACTIONS.DROP) then
            
                if not buffaction.invobject.components.equippable.isequipped then 
                    self.inst.components.inventory_2:Equip(buffaction.invobject)
                end
                
                if self.inst.components.inventory_2:GetActiveItem() == buffaction.invobject then
                    self.inst.components.inventory_2:SetActiveItem(nil)
                end
        end
        
        self.inst.components.locomotor:PushAction(buffaction, true)
    end    

end





return PlayerController_2
