-- @outline // PUBLIC METHODS

function Controller:Update(dt)
	local Character = System.LocalPlayer and System.LocalPlayer.Character
	if not Character then return end
	
	local Humanoid : Humanoid = Character.Humanoid
	
	if self.ListenForInput then
		if System.Control.InputMethod == Enum.UserInputType.Gamepad1 then
			self.MoveDirection = System.Control.ThumbstickDirection1
		else
			self.MoveDirection = Vector2.new(self.Inputs.S - self.Inputs.W, self.Inputs.A - self.Inputs.D)
		end
	end
	
	if self.MoveDirection == Vector2.zero then
		if self.ForceMove ~= 0 then
			local MousePos = System.Aim.MousePos
			if not MousePos then return end
			
			local StartPos = Vector2.new(Character.HumanoidRootPart.Position.X, Character.HumanoidRootPart.Position.Z)
			self.MoveDirection = (MousePos - StartPos).Unit
			
			self:ApplyMove(self.MoveDirection, dt, Humanoid)
		else
			self:ApplyMove(Vector2.zero, dt, Humanoid)
		end
		return
	end
	
	self:CalculateRelativeMoveDirection()
	self:ApplyMove(self.MoveDirection, dt, Humanoid)
end

function Controller:CalculateRelativeMoveDirection()
	self.MoveDirection = self.MoveDirection.Unit

	local cos = math.cos(math.rad(System.Camera.Angle))
	local sin = math.sin(math.rad(System.Camera.Angle))
	self.MoveDirection = Vector2.new(self.MoveDirection.X * cos - self.MoveDirection.Y * sin, self.MoveDirection.X * sin + self.MoveDirection.Y * cos)
end

function Controller:ApplyMove(NewMoveDirection, dt, Humanoid)
	self.CachedDirection = System.Interpolate.Linear(self.CachedDirection or Vector2.new(), NewMoveDirection, math.clamp(dt/self.SmoothTime, 0, 1))
	self.FinalDirection = Vector3.new(self.CachedDirection.X, 0, self.CachedDirection.Y) * (self.ForceMove ~= 0 and self.ForceMove or 1)
	
	Humanoid:Move(self.FinalDirection)
end
