Vector = dofile_once("mods/spellbound_bundle/files/scripts/misc/vector.lua")
dofile_once( "mods/spellbound_bundle/files/scripts/utils.lua");

local id = 21412
local function new_id()
	id = id + 1
	return id
end

gui = gui or GuiCreate()

GuiStartFrame(gui)

local projectile = GetUpdatedEntityID()

--print(tostring(projectile))


if(EntityHasFlag(projectile, "destroyed"))then
	GuiDestroy(gui)
	return
end



iteration = iteration or 0

local function DrawLine(vector1, vector2, r, g, b, a)

	a = a or 1

	-- get direction, distance, and center point between points
	local dx = vector2.x - vector1.x
	local dy = vector2.y - vector1.y
	local dist = math.sqrt(dx * dx + dy * dy)

	-- normalize direction
	dx = dx / dist
	dy = dy / dist

	-- figure out rotation angle in direction, in radians
	local angle = math.atan2(dy, dx)

	GuiColorSetForNextWidget(gui, 0, 1, 0, 1)

	GuiColorSetForNextWidget(gui, r, g, b, 1)
	GuiImage(gui, new_id(), vector1.x, vector1.y, "mods/spellbound_bundle/files/gfx/ui_gfx/pixel.png", a, dist, 1, angle)
end

local function vec_rotate(x, y, angle)
	local ca = math.cos(angle)
	local sa = math.sin(angle)
	local px = ca * x - sa * y
	local py = sa * x + ca * y
	return px,py
end

local function ui_pos(x, y)

	local virt_x = MagicNumbersGetValue("VIRTUAL_RESOLUTION_X")
	local virt_y = MagicNumbersGetValue("VIRTUAL_RESOLUTION_Y")
	local screen_width, screen_height = GuiGetScreenDimensions(gui)
	local scale_x = virt_x / screen_width
	local scale_y = virt_y / screen_height
	local cx, cy = GameGetCameraPos()
	local sx, sy = (x - cx) / scale_x + screen_width / 2 + 1.5, (y - cy) / scale_y + screen_height / 2
	return sx, sy
end

local function vector_ui_pos(vec)
	return Vector.new(ui_pos(vec.x, vec.y))
end


if(projectile ~= nil and projectile ~= 0)then
	local x, y = EntityGetTransform(projectile)

	local velocity_comp = EntityGetFirstComponentIncludingDisabled(projectile, "VelocityComponent")
	local vel_x, vel_y = ComponentGetValue2(velocity_comp, "mVelocity")

	-- get direction based on velocity
	local dx = vel_x
	local dy = vel_y
	local dist = math.sqrt(dx * dx + dy * dy)
	-- normalize
	dx = dx / dist
	dy = dy / dist
	
	local radius = 100
	local fov = 45 -- degrees

	-- find homing targets in range
	local targets = EntityGetInRadiusWithTag(x, y, radius, "homing_target")

	local closest_target = nil
	local closest_dist = radius
	
	for i, target in ipairs(targets) do
		local target_x, target_y = EntityGetTransform(target)
		local dist = math.sqrt((target_x - x) * (target_x - x) + (target_y - y) * (target_y - y))
		if(dist < closest_dist or closest_target == nil)then
			closest_target = target
			closest_dist = dist
		end
	end

	local angle_offset = (fov / 2) * math.pi / 180

	local offset_left_x, offset_left_y = vec_rotate(dx, dy, -angle_offset)
	local offset_right_x, offset_right_y = vec_rotate(dx, dy, angle_offset)

	local left_x, left_y = ui_pos(x + offset_left_x * radius, y + offset_left_y * radius)
	local right_x, right_y = ui_pos(x + offset_right_x * radius, y + offset_right_y * radius)

	local pv = Vector.new(x, y)
	
	DrawLine(vector_ui_pos(pv), Vector.new(left_x, left_y), 1, 1, 1, 0.2)
	DrawLine(vector_ui_pos(pv), Vector.new(right_x, right_y), 1, 1, 1, 0.2)

	if(closest_target ~= nil)then
		-- check if target position is within 45 degrees of projectile direction
		local target_x, target_y = EntityGetTransform(closest_target)
		local target_dx = target_x - x
		local target_dy = target_y - y
		local target_dist = math.sqrt(target_dx * target_dx + target_dy * target_dy)
		target_dx = target_dx / target_dist
		target_dy = target_dy / target_dist
		local dot = dx * target_dx + dy * target_dy
		
		if(dot > math.cos(fov / 2 * math.pi / 180))then
			local hitbox = EntityGetFirstComponentIncludingDisabled( closest_target, "HitboxComponent" );
			if(hitbox ~= nil)then

				iteration = iteration + 1

				local min_x = ComponentGetValue2(hitbox, "aabb_min_x")
				local min_y = ComponentGetValue2(hitbox, "aabb_min_y")
				local max_x = ComponentGetValue2(hitbox, "aabb_max_x")
				local max_y = ComponentGetValue2(hitbox, "aabb_max_y")
	
				-- get all corners
				local corners = {
					Vector.new(target_x + min_x, target_y + min_y),
					Vector.new(target_x + max_x, target_y + min_y),
					Vector.new(target_x + max_x, target_y + max_y),
					Vector.new(target_x + min_x, target_y + max_y),
				}

				local target = Vector.new(target_x, target_y)

				local function get_normals(corners)
					return {
						{corners[1], (corners[1] - corners[4]):normalize(), (corners[1] - corners[2]):normalize()},
						{corners[2], (corners[2] - corners[1]):normalize(), (corners[2] - corners[3]):normalize()},
						{corners[3], (corners[3] - corners[2]):normalize(), (corners[3] - corners[4]):normalize()},
						{corners[4], (corners[4] - corners[1]):normalize(), (corners[4] - corners[3]):normalize()},
					}
				end

				local normals = get_normals(corners)
				for _, set in ipairs(normals)do
					local c = 0;
					local lv = (set[1] - pv):normalize()
					for i = 2, 3 do
						c = set[i]:dot(lv) <= 0 and c + 1 or c
					end
					if c == 1 then

						local closest_vector = nil
						
						local point = vector_ui_pos(pv) + (vector_ui_pos(pv):direction(vector_ui_pos(set[1])) * radius)

						local distance1 = Vector.new(left_x, left_y):distance(point)
						local distance2 = Vector.new(right_x, right_y):distance(point)

						if(distance1 < distance2)then
							closest_vector = Vector.new(left_x, left_y)
						else
							closest_vector = Vector.new(right_x, right_y)
						end

						DrawLine(vector_ui_pos(pv), closest_vector:lerp(point, math.min(1, iteration / 10)), 1, 0, 0, 0.8)

						local speed = Vector.new(vel_x, vel_y):len()
						local direction_to_center = pv:direction(target)
						local vel_to_center = direction_to_center * speed

						ComponentSetValue2(velocity_comp, "mVelocity", vel_to_center.x, vel_to_center.y)
					end
				end
			end

		end

	else

		iteration = 0
	end
end