local v=require((game:GetService("\082\101\112\108\105\099\097\116\101\100\083\116\111\114\097\103\101")):WaitForChild("\078\101\118\101\114\109\111\114\101"))local m=v("\083\105\103\110\097\108")local u=v("\077\097\105\100")local q={}q.ClassName="\086\097\108\117\101\079\098\106\101\099\116"function q.new(v)local d={}rawset(d,"\095\118\097\108\117\101",v)d._maid=u.new()d.Changed=m.new()d._maid:GiveTask(d.Changed)return setmetatable(d,q)end function q.__index(m,v)if v=="\086\097\108\117\101"then return m._value elseif q[v]then return q[v]elseif v=="\095\118\097\108\117\101"then return nil else error(("\037\113 \105\115 \110\111\116 \097 \109\101\109\098\101\114 \111\102 \086\097\108\117\101\079\098\106\101\099\116"):format(tostring(v)))end end function q.__newindex(q,v,m)if v=="\086\097\108\117\101"then local v=rawget(q,"\095\118\097\108\117\101",m)if v~=m then rawset(q,"\095\118\097\108\117\101",m)local d=u.new()q._maid._valueMaid=d q.Changed:Fire(m,v,d)end else error(("\037\113 \105\115 \110\111\116 \097 \109\101\109\098\101\114 \111\102 \086\097\108\117\101\079\098\106\101\099\116"):format(tostring(v)))end end function q.Destroy(v)v.Value=nil v._maid:DoCleaning()end return q
--- To work like value objects in ROBLOX and track a single item,
-- with `.Changed` events
-- @classmod ValueObject

local require = require(game:GetService("ReplicatedStorage"):WaitForChild("Nevermore"))

local Signal = require("Signal")
local Maid = require("Maid")

local ValueObject = {}
ValueObject.ClassName = "ValueObject"

--- The value of the ValueObject
-- @tfield Variant Value

--- Event fires when the value's object value change
-- @signal Changed
-- @tparam Variant newValue The new value
-- @tparam Variant oldValue The old value


--- Constructs a new value object
-- @constructor
-- @treturn ValueObject
function ValueObject.new(baseValue)
	local self = {}

	rawset(self, "_value", baseValue)

	self._maid = Maid.new()

	self.Changed = Signal.new() -- :Fire(newValue, oldValue, maid)
	self._maid:GiveTask(self.Changed)

	return setmetatable(self, ValueObject)
end

function ValueObject:__index(index)
	if index == "Value" then
		return self._value
	elseif ValueObject[index] then
		return ValueObject[index]
	elseif index == "_value" then
		return nil -- Edge case
	else
		error(("%q is not a member of ValueObject"):format(tostring(index)))
	end
end

function ValueObject:__newindex(index, value)
	if index == "Value" then
		local previous = rawget(self, "_value", value)
		if previous ~= value then
			rawset(self, "_value", value)

			local maid = Maid.new()
			self._maid._valueMaid = maid
			self.Changed:Fire(value, previous, maid)
		end
	else
		error(("%q is not a member of ValueObject"):format(tostring(index)))
	end
end

--- Forces the value to be nil on cleanup, cleans up the Maid
function ValueObject:Destroy()
	self.Value = nil
	self._maid:DoCleaning()
end

return ValueObject
