local K={}local U U={default=function(K,U)local u={}u.Object=K u.Size=U function u.getPosition(K)return K.Object.CFrame.Position end function u.getFCP(K)return K.Object.CFrame.Position+(K.Object.CFrame.LookVector*K.Size.Z)/2 end return u end,defaultWithoutSize=function(K)local U={}U.Object=K function U.getPosition(K)return K.Object.CFrame.Position end function U.getFCP(K)return K:getPosition()end return U end,defaultOnlyPosition=function(K)local U={}U.Object=K function ObjectTracker.getPosition(K)return K.Object.Position end function ObjectTracker.getFCP(K)return K:getPosition()end return U end,model=function(K)return U.default(K.PrimaryPart,K.PrimaryPart.Size)end;tool=function(K)return U.default(K.Handle,K.Handle.Size)end}local function u(K,U,u)local e,M=pcall(function()return typeof(K[U])==u end)return e and M end local function e(K)return u(K,"\083\105\122\101","\086\101\099\116\111\114\051")end local function M(K)return u(K,"\067\070\114\097\109\101","\067\070\114\097\109\101")end local function X(K)return u(K,"\080\111\115\105\116\105\111\110","\086\101\099\116\111\114\051")end function K.new(K,u)assert((K and typeof(K)=="\073\110\115\116\097\110\099\101")and not u or typeof(u)=="\086\101\099\116\111\114\051","\087\114\111\110\103 \097\114\103\117\109\101\110\116\115 \103\105\118\105\110\103 \116\111 \079\098\106\101\099\116\084\114\097\099\107\101\114 \067\111\110\115\116\114\117\099\116\111\114")if K:IsA("\077\111\100\101\108")and K.PrimaryPart then return U.model(K)elseif K:IsA("\084\111\111\108")and K:FindFirstChild("\072\097\110\100\108\101")then return U.tool(K)elseif M(K)then if e(K)then return U.default(K,K.Size)elseif u then return U.default(K,u)else return U.defaultWithoutSize(K)end elseif X(K)then return U.defaultOnlyPosition(K)else error("\084\104\097\116 \116\121\112\101 \111\102 \105\110\115\116\097\110\099\101 \105\115 \110\111\116 \115\117\112\112\111\114\116\101\100")end end return K
local module = {}

local constructors
constructors = {
    default = function(object, size) -- all features supported
        local ObjectTracker = {}
        ObjectTracker.Object = object
        ObjectTracker.Size = size
        function ObjectTracker:getPosition()
            return self.Object.CFrame.Position
        end
        function ObjectTracker:getFCP() --getFrontCenterPosition
            return self.Object.CFrame.Position + self.Object.CFrame.LookVector * self.Size.Z/2  -- or part.CFrame * CFrame.new(0, 0, part.Size.Z/-2)
        end
        return ObjectTracker
    end,
    defaultWithoutSize = function(object) -- no features supported
        local ObjectTracker = {}
        ObjectTracker.Object = object -- also used as key when key not given
        function ObjectTracker:getPosition()
            return self.Object.CFrame.Position
        end
        function ObjectTracker:getFCP() -- no support
            return self:getPosition()
        end
        return ObjectTracker
    end,
    defaultOnlyPosition = function(object) -- no features supported
        local ObjetTracker = {}
        ObjetTracker.Object = object -- also used as key when key not given
        function ObjectTracker:getPosition()
            return self.Object.Position
        end
        function ObjectTracker:getFCP() -- no support
            return self:getPosition()
        end
        return ObjetTracker
    end,
    model = function(model) -- all features supported
       return constructors.default(model.PrimaryPart, model.PrimaryPart.Size)
    end,
    tool= function(tool) -- all features supported
        return constructors.default(tool.Handle, tool.Handle.Size)
    end
}


local function hasProp(object, prop, proptype)
    local suc, res = pcall(function()
        return typeof(object[prop]) == proptype
    end)
    return suc and res
end

local function hasSize(object)
   return hasProp(object,"Size","Vector3")
end

local function hasCFrame(object)
    return hasProp(object, "CFrame", "CFrame")
end

local function hasPosition(object)
    return hasProp(object, "Position", "Vector3")
end

function module.new(object, Size) -- first param can be anything that has a CFrame property/model/tool, second is optional, if the object doesnt have a size property then you can give it one, its for the frontedge feature
   assert( (object and typeof(object) == "Instance") and not Size or typeof(Size) == "Vector3", "Wrong arguments giving to ObjectTracker Constructor")
   
   if object:IsA("Model") and object.PrimaryPart then -- must have a PP
        return constructors.model(object)
   elseif object:IsA("Tool") and object:FindFirstChild("Handle") then -- must have a Handle
        return constructors.tool(object)
   elseif hasCFrame(object) then -- every other thing that has a CFrame is supported like camera, part, etc
        if hasSize(object) then
            return constructors.default(object, object.Size)
        elseif Size then
            return constructors.default(object, Size)
        else -- no support for FCP feature
            return constructors.defaultWithoutSize(object)
        end
    elseif hasPosition(object) then -- no support for FCP feature
        return constructors.defaultOnlyPosition(object)
   else
        error("That type of instance is not supported")
   end
end

return module