local utils = require "scripts.utils"

-- Input Variables
local dragging = false

-- Camera Variables
local inv_matrix -- inverse matrix cached on drag start

-- Position Variables
local start_pos = vmath.vector3()
local prev_pos = vmath.vector3()

function on_reload(self)
	-- TODO: Investigate why using `local` wasn't working on reload
	-- msg.post(".", "acquire_input_focus")
	-- -- NOTE: For some reason I need to also call this on_reload, or else it gets niled out
	-- self.rts_camera = msg.url("CameraParent#camera")
	-- local DISPLAY_WIDTH = sys.get_config_int("display.width")
	-- local DISPLAY_HEIGHT = sys.get_config_int("display.height")
	-- self.rts_camera_size = vmath.vector3(DISPLAY_WIDTH, DISPLAY_HEIGHT, 0)
	self.selection_collider = msg.url("/selection_box#collisionobject")
end

function init(self)
	msg.post(".", "acquire_input_focus")            -- Activates to get inputs
	self.selection_box = msg.url("#selection_box")       -- Selection Box - Sprite Component
	msg.post(self.selection_box, "disable")              -- Sprite Hidden
	self.rts_camera = msg.url("CameraParent#camera") -- Camera Component2
	self.selection_collider = msg.url("#selection_box/collisionobject")
		-- Gets Display Properties from System
	local DISPLAY_WIDTH = sys.get_config_int("display.width")
	local DISPLAY_HEIGHT = sys.get_config_int("display.height")

	-- Get Screen To World Properties
	self.rts_camera_size = vmath.vector3(DISPLAY_WIDTH, DISPLAY_HEIGHT, 0)
end

local function selection_update_start(self, action)         -- Runs once when pressed	
	-- Updates Screen_to_World Variables
	local projection = camera.get_projection(self.rts_camera) -- Gets the Projection Size
	local view = camera.get_view(self.rts_camera)          -- Gets the View Size
	inv_matrix = vmath.inv(projection * view)         -- Gets the Inversion

	-- Initialize positions
	local x, y, _ = utils.screen_to_world(action.x, action.y, 0, "/CameraParent#camera") -- Gets Global Position
	start_pos.x, start_pos.y = x, y               -- Sets start_pos
	prev_pos.x, prev_pos.y = x, y                 -- Updates prev_pos

	-- Update Sprite Properties
	go.set_position(start_pos, self.selection_box)              -- Set Position
	go.set(self.selection_box, "size", vmath.vector3(0.1, 0.1, -1)) -- Set Size(0.1) in X, Y
	msg.post(self.selection_box, "enable")                      -- Sprite Visable
	msg.post("/selection_box#collisionobject", "enable")
	dragging = true                                        -- Dragging True
end

local function selection_update_dragging(self, x, y) -- Runs when Dragging
	-- Calculate bounding box
	local min_x = math.min(start_pos.x, x)     -- Min X
	local min_y = math.min(start_pos.y, y)     -- Min Y
	local max_x = math.max(start_pos.x, x)     -- Max X
	local max_y = math.max(start_pos.y, y)     -- Max Y

	-- Calculates the center of the selection box
	local center = vmath.vector3((min_x + max_x) * 0.5,	(min_y + max_y) * 0.5,	0)

	-- Calculate width/height of the selection box from drag distance
	-- Ensures a minimum size of 0.1 to prevent the sprite from collapsing
	local size = vmath.vector3(math.max(max_x - min_x, 0.1),math.max(max_y - min_y, 0.1),0)

	-- Set sprite properties
	go.set_position(center, self.selection_box) -- Sets Position
	go.set(self.selection_box, "size", size) -- Sets Size
	-- go.set(self.selection_collider, "size", size)
	local box = physics.get_shape("/selection_box#collisionobject", "box")
	box.dimensions = size
	physics.set_shape("/selection_box#collisionobject", "box", box)
end

function on_input(self, action_id, action)
	if action_id ~= hash("touch") then return end

	if action.pressed and not dragging then
		selection_update_start(self, action)             -- Applies Sprite Properties at Start
	elseif action.released and dragging then
		dragging = false                           -- Dragging False
		msg.post(self.selection_box, "disable")         -- Sprite Hidden
		msg.post("/selection_box#collisionobject", "disable")
	elseif dragging then
		local x, y = utils.screen_to_world(action.x, action.y, 0, "/CameraParent#camera") -- Gets Global Position

		-- Only update if position changed
		if math.abs(x - prev_pos.x) > 0.001 or math.abs(y - prev_pos.y) > 0.001 then
			prev_pos.x, prev_pos.y = x, y -- Updates prev_pos

			selection_update_dragging(self, x, y) -- Applies Sprite Properties during dragging
		end
	end
end