dofile("../defs/intent_defs.lua")

local PlayerInputSystem = inherited("PlayerInputSystem", SystemMap)

function PlayerInputSystem:new()
	local ms = instance(self)
	return ms
end

function PlayerInputSystem:wants(ent)
	return ent.aspects.player_input
end

function PlayerInputSystem:ent_added(ent)	
	assert(ent.player, "no player")
end

function PlayerInputSystem:ent_removed(ent)
end

local action_delta = {
	left = {x = -1, y = 0},
	right = {x = 1, y = 0},
	up = {x = 0, y = -1},
	down = {x = 0, y = 1},
}

function PlayerInputSystem:step(dt)
	local world = self.world
	for ent, _ in pairs(self.ents) do
		local player = ent.player
		local input = player.input

		--movement
		local dx,dy = 0,0
		for action_name, def in pairs(action_delta) do
			if input:is_held(action_name) then
				dx = dx + def.x
				dy = dy + def.y
			end
		end
		local dist = math.min(1,math.distance(0,0,dx,dy))
		local thrust_angle = math.angleBetweenPoints(0,0,dx,dy)
		ent:set_input_vector(thrust_angle, dist)		

		--looking
		local cursor = input.cursor
		local cx, cy = cursor.camera_x, cursor.camera_y
		local look_angle = math.angleBetweenPoints(ent.x,ent.y,cx,cy)		
		ent:set_look_angle(look_angle)
		if cx > ent.x then
			ent:set_flip(false)
		elseif cx < ent.x then
			ent:set_flip(true)
		end

		local primary_pressed = input:is_pressed("primary")
		local primary_released = input:is_released("primary")
		local primary_held = input:is_held("primary")

		local secondary_pressed = input:is_pressed("secondary")
		local secondary_released = input:is_released("secondary")
		local secondary_held = input:is_held("secondary")

		local hoverd_eaten = false
		
		if primary_released then
			ent:released_action_intent("primary")
			ent:released_action_intent("hud")			
		end
		if secondary_released then
			ent:released_action_intent("secondary")
		end

		if ent:get_action_intent("primary") then
			hoverd_eaten = true
		end

		local hovered_element
		if not hoverd_eaten then
			hovered_element = player:get_hovered_element()
			--print("JOv", hovered_element)
			if hovered_element then
				hoverd_eaten = true
			end
		end

		if ent.hover_delay > 0 then
			ent.hover_delay = ent.hover_delay - dt
			hoverd_eaten = true
		end
		--if not primary_held then		
		local pickupable_system = world:get_system_by_key("pickupables")
		if pickupable_system then
			local pickups_map = pickupable_system:get_pickupables_map()
			local best = nil
			local best_dist2 = nil
			
			local inventory = ent.inventory
			local pull_range2 = ent.pickup_pull_range^2
			for pickup,_ in pairs(pickups_map) do
				local dist2 = math.distance2(cx,cy, pickup.x, pickup.y)
				
				if not hoverd_eaten then
					local radius2 = pickup.pickup_radius^2
					if dist2 < radius2 then
						if not best_dist2 or dist2 < best_dist2 then
							best = pickup
							best_dist2 = dist2
							hoverd_eaten = true
						end
					end
				end

				local auto_pickup = pickup.auto_pickup
				local item = pickup.item
				local item_slot = item:get_slot_type()
				if inventory:has_free_slot_of_type(item_slot) then
					auto_pickup = true
				end
				if auto_pickup and pickup.z <= 0 then
					if dist2 < pull_range2 then
						ent:set_desired_pickup(pickup)
					end
				end
			end

			if best or ent.hovered_pickup then
				ent:set_hovered_pickup(best)
			end
		end

		local keeper = player.keeper
		if keeper then
			if keeper.customer ~= ent then
				player:set_shop_keeper_gui(nil)
			end
		end

		local shop_keepers = world:get_system_by_key("shop_keepers")
		if shop_keepers then
			local best_keeper = nil
			local best_dist2 = (ent.shopping_range*0.25)^2
			if not hoverd_eaten then
				for keeper, _ in pairs(shop_keepers:get_shop_keepers_map()) do
					if keeper.customer == ent then
						--we got an offer
						local dist2 = math.distance2(cx,cy, keeper.x, keeper.y)
						if dist2 < best_dist2 then
							best_dist2 = dist2
							best_keeper = keeper
							hoverd_eaten = true
						end
					end
				end
			end
			if best_keeper ~= ent.hovered_keeper then
				ent:set_hovered_keeper(best_keeper)
			end
		end

		local named_target_system = world:get_system_by_key("named_target")
		if named_target_system then
			local best_target = nil
			local best_dist2 = (ent.highlight_radius)^2
			if not hoverd_eaten then
				for target, _ in pairs(named_target_system:get_named_targets_map()) do
					local dist2 = math.distance2(cx,cy, target.x, target.y)
					if dist2 < best_dist2 then
						best_dist2 = dist2
						best_target = target
					end				
				end
			end
			if best_target ~= ent.hovered_target then				
				ent:set_hovered_target(best_target)
				if best_target then
					hoverd_eaten = true
				end
			end
		end


		ent:step_action_intents()
		
		--actions		
		if primary_pressed then
			
			local hovered_keeper = ent.hovered_keeper

			if hovered_element then
				ent:set_action_intent("hud", "hovered_element")
				--print(1)
			elseif hovered_keeper then
				ent:set_action_intent("interact", "browse_keeper")
				--print(2)
			elseif ent.hovered_pickup then	
				ent:set_action_intent("primary", "pickup")
				ent:set_action_intent("interact", nil)
				--print(3)
			else
				ent:set_action_intent("primary", "melee")
				ent:set_action_intent("interact", nil)
				--print(4)
				--world.universe:is_line_of_sight_blocked(ent.x, ent.y, cx, cy)
			end
		end

		if secondary_pressed then
			local hovered_element = player:get_hovered_element()			
			--if hovered_element then
				--ent:set_action_intent("primary", "hovered_element")
			--elseif ent.hovered_pickup then	
				--ent:set_action_intent("primary", "pickup")
			--else
			ent:set_action_intent("secondary", "ranged")	
			ent:set_action_intent("interact", nil)
			--end
		end
	end
end

return PlayerInputSystem