local Q=import("\046\047\102\117\110\099\116\105\111\110\115\047\116\121\112\101\111\102")local T=import("\046\047\097\115\115\105\103\110")local t={}function t.normal(Q)return T({},{get=function(Q,T)return(getmetatable(Q)).instance.properties[T]end;set=function(Q,T,t)(getmetatable(Q)).instance.properties[T]=t end;getDefault=function()return nil end},Q)end function t.readOnly(Q)return T(t.normal(Q),{set=function(Q,T,t)error(string.format("\085\110\097\098\108\101 \116\111 \097\115\115\105\103\110 \112\114\111\112\101\114\116\121 \037\115\046 \083\099\114\105\112\116 \119\114\105\116\101 \097\099\099\101\115\115 \105\115 \114\101\115\116\114\105\099\116\101\100\046",T))end},Q)end function t.typed(N,j)return T(t.normal(j),{set=function(T,t,j)local a=Q(j)if a~=N then error(string.format("\037\115 \109\117\115\116 \098\101 \111\102 \116\121\112\101 \037\115\044 \114\101\099\101\105\118\101\100 \116\121\112\101 \037\115",t,N,a),2)end;(getmetatable(T)).instance.properties[t]=j end},j)end function t.enum(N,j)return T(t.normal(j),{set=function(T,t,j)local a=Q(j)if a~="\069\110\117\109\073\116\101\109"then error(string.format("\069\120\112\101\099\116\101\100 \101\110\117\109 \102\114\111\109 \037\115\044 \114\101\099\101\105\118\101\100 \116\121\112\101 \037\115",tostring(N),a),2)end if j.EnumType~=N then error(string.format("\069\120\112\101\099\116\101\100 \101\110\117\109 \102\114\111\109 \037\115\044 \103\111\116 \101\110\117\109 \102\114\111\109 \037\115",tostring(N),tostring(j.EnumType)),2)end;(getmetatable(T)).instance.properties[t]=j end},j)end return t
local typeof = import("./functions/typeof")
local assign = import("./assign")

local InstanceProperty = {}

function InstanceProperty.normal(config)
	return assign({}, {
		get = function(self, key)
			return getmetatable(self).instance.properties[key]
		end,
		set = function(self, key, value)
			getmetatable(self).instance.properties[key] = value
		end,
		getDefault = function()
			return nil
		end,
	}, config)
end

function InstanceProperty.readOnly(config)
	return assign(InstanceProperty.normal(config), {
		set = function(self, key, value)
			error(string.format("Unable to assign property %s. Script write access is restricted.", key))
		end,
	}, config)
end

--[[
	This method forces the value of a setter to be typed.

	`type` is a string paramater that is compared to typeof(value)
]]
function InstanceProperty.typed(type, config)
	return assign(InstanceProperty.normal(config), {
		set = function(self, key, value)
			local passedType = typeof(value)

			if passedType ~= type then
				error(string.format("%s must be of type %s, received type %s", key, type, passedType), 2)
			end

			getmetatable(self).instance.properties[key] = value
		end,
	}, config)
end

function InstanceProperty.enum(enum, config)
	return assign(InstanceProperty.normal(config), {
		set = function(self, key, value)
			local passedType = typeof(value)

			if passedType ~= "EnumItem" then
				error(string.format("Expected enum from %s, received type %s", tostring(enum), passedType), 2)
			end

			if value.EnumType ~= enum then
				error(string.format("Expected enum from %s, got enum from %s", tostring(enum), tostring(value.EnumType)), 2)
			end

			getmetatable(self).instance.properties[key] = value
		end,
	}, config)
end

return InstanceProperty