local Z=import("\046\047\102\117\110\099\116\105\111\110\115\047\116\121\112\101\111\102")local D=import("\046\047\097\115\115\105\103\110")local Q={}function Q.normal(Z)return D({},{get=function(Z,D)return(getmetatable(Z)).instance.properties[D]end,set=function(Z,D,Q)(getmetatable(Z)).instance.properties[D]=Q end,getDefault=function()return nil end},Z)end function Q.readOnly(Z)return D(Q.normal(Z),{set=function(Z,D,Q)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",D))end},Z)end function Q.typed(j,O)return D(Q.normal(O),{set=function(D,Q,O)local L=Z(O)if L~=j 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",Q,j,L),2)end;(getmetatable(D)).instance.properties[Q]=O end},O)end function Q.enum(j,O)return D(Q.normal(O),{set=function(D,Q,O)local L=Z(O)if L~="\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(j),L),2)end if O.EnumType~=j 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(j),tostring(O.EnumType)),2)end;(getmetatable(D)).instance.properties[Q]=O end},O)end return Q
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