local function s(s,N,g)local b=Replicas[s]local I=b.Data local D=b._table_listeners for s=1,#N-1,1 do I=I[N[s]]if D~=nil then D=D[1][N[s]]end end local Q=N[#N]local n=I[Q]I[Q]=g if n~=g and D~=nil then if n==nil then if D[3]~=nil then for s,N in ipairs(D[3])do N(g,Q)end end end D=D[1][N[#N]]if D~=nil then if D[2]~=nil then for s,N in ipairs(D[2])do N(g,n)end end end end for s,b in ipairs(b._raw_listeners)do b("\083\101\116\086\097\108\117\101",N,g)end end local function N(s,N,g)local b=Replicas[s]local I=b.Data local D=b._table_listeners for s=1,#N,1 do I=I[N[s]]if D~=nil then D=D[1][N[s]]end end for s,N in pairs(g)do local g=I[s]I[s]=N if g~=N and D~=nil then if g==nil then if D[3]~=nil then for g,b in ipairs(D[3])do b(N,s)end end end local b=D[1][s]if b~=nil then if b[2]~=nil then for s,b in ipairs(b[2])do b(N,g)end end end end end for s,b in ipairs(b._raw_listeners)do b("\083\101\116\086\097\108\117\101\115",N,g)end end local function g(s,N,g)local b=Replicas[s]local I=b.Data local D=b._table_listeners for s=1,#N,1 do I=I[N[s]]if D~=nil then D=D[1][N[s]]end end table.insert(I,g)local Q=#I if D~=nil then if D[4]~=nil then for s,N in ipairs(D[4])do N(Q,g)end end end for s,b in ipairs(b._raw_listeners)do b("\065\114\114\097\121\073\110\115\101\114\116",N,g,Q)end return Q end local function b(s,N,g,b)local I=Replicas[s]local D=I.Data local Q=I._table_listeners for s=1,#N,1 do D=D[N[s]]if Q~=nil then Q=Q[1][N[s]]end end D[g]=b if Q~=nil then if Q[5]~=nil then for s,N in ipairs(Q[5])do N(g,b)end end end for s,I in ipairs(I._raw_listeners)do I("\065\114\114\097\121\083\101\116",N,g,b)end end local function I(s,N,g)local b=Replicas[s]local I=b.Data local D=b._table_listeners for s=1,#N,1 do I=I[N[s]]if D~=nil then D=D[1][N[s]]end end local Q=table.remove(I,g)if D~=nil then if D[6]~=nil then for s,N in ipairs(D[6])do N(g,Q)end end end for s,b in ipairs(b._raw_listeners)do b("\065\114\114\097\121\082\101\109\111\118\101",N,g,Q)end return Q end
-- Write handlers:

local function ReplicaSetValue(replica_id, path_array, value)
	local replica = Replicas[replica_id]
	-- Getting path pointer and listener table:
	local pointer = replica.Data
	local listeners = replica._table_listeners
	for i = 1, #path_array - 1 do
		pointer = pointer[path_array[i]]
		if listeners ~= nil then
			listeners = listeners[1][path_array[i]]
		end
	end
	-- Setting value:
	local key = path_array[#path_array]
	local old_value = pointer[key]
	pointer[key] = value
	-- Signaling listeners:
	if old_value ~= value and listeners ~= nil then
		if old_value == nil then
			if listeners[3] ~= nil then -- "NewKey" listeners
				for _, listener in ipairs(listeners[3]) do
					listener(value, key)
				end
			end
		end
		listeners = listeners[1][path_array[#path_array]]
		if listeners ~= nil then
			if listeners[2] ~= nil then -- "Change" listeners
				for _, listener in ipairs(listeners[2]) do
					listener(value, old_value)
				end
			end
		end
	end
	-- Raw listeners:
	for _, listener in ipairs(replica._raw_listeners) do
		listener("SetValue", path_array, value)
	end
end

local function ReplicaSetValues(replica_id, path_array, values)
	local replica = Replicas[replica_id]
	-- Getting path pointer and listener table:
	local pointer = replica.Data
	local listeners = replica._table_listeners
	for i = 1, #path_array do
		pointer = pointer[path_array[i]]
		if listeners ~= nil then
			listeners = listeners[1][path_array[i]]
		end
	end
	-- Setting values:
	for key, value in pairs(values) do
		-- Set value:
		local old_value = pointer[key]
		pointer[key] = value
		-- Signaling listeners:
		if old_value ~= value and listeners ~= nil then
			if old_value == nil then
				if listeners[3] ~= nil then -- "NewKey" listeners
					for _, listener in ipairs(listeners[3]) do
						listener(value, key)
					end
				end
			end
			local key_listeners = listeners[1][key]
			if key_listeners ~= nil then
				if key_listeners[2] ~= nil then -- "Change" listeners
					for _, listener in ipairs(key_listeners[2]) do
						listener(value, old_value)
					end
				end
			end
		end
	end
	-- Raw listeners:
	for _, listener in ipairs(replica._raw_listeners) do
		listener("SetValues", path_array, values)
	end
end

local function ReplicaArrayInsert(replica_id, path_array, value) --> new_index
	local replica = Replicas[replica_id]
	-- Getting path pointer and listener table:
	local pointer = replica.Data
	local listeners = replica._table_listeners
	for i = 1, #path_array do
		pointer = pointer[path_array[i]]
		if listeners ~= nil then
			listeners = listeners[1][path_array[i]]
		end
	end
	-- Setting value:
	table.insert(pointer, value)
	-- Signaling listeners:
	local new_index = #pointer
	if listeners ~= nil then
		if listeners[4] ~= nil then -- "ArrayInsert" listeners
			for _, listener in ipairs(listeners[4]) do
				listener(new_index, value)
			end
		end
	end
	-- Raw listeners:
	for _, listener in ipairs(replica._raw_listeners) do
		listener("ArrayInsert", path_array, value, new_index)
	end
	return new_index
end

local function ReplicaArraySet(replica_id, path_array, index, value)
	local replica = Replicas[replica_id]
	-- Getting path pointer and listener table:
	local pointer = replica.Data
	local listeners = replica._table_listeners
	for i = 1, #path_array do
		pointer = pointer[path_array[i]]
		if listeners ~= nil then
			listeners = listeners[1][path_array[i]]
		end
	end
	-- Setting value:
	pointer[index] = value
	-- Signaling listeners:
	if listeners ~= nil then
		if listeners[5] ~= nil then -- "ArraySet" listeners
			for _, listener in ipairs(listeners[5]) do
				listener(index, value)
			end
		end
	end
	-- Raw listeners:
	for _, listener in ipairs(replica._raw_listeners) do
		listener("ArraySet", path_array, index, value)
	end
end

local function ReplicaArrayRemove(replica_id, path_array, index) --> removed_value
	local replica = Replicas[replica_id]
	-- Getting path pointer and listener table:
	local pointer = replica.Data
	local listeners = replica._table_listeners
	for i = 1, #path_array do
		pointer = pointer[path_array[i]]
		if listeners ~= nil then
			listeners = listeners[1][path_array[i]]
		end
	end
	-- Setting value:
	local old_value = table.remove(pointer, index)
	-- Signaling listeners:
	if listeners ~= nil then
		if listeners[6] ~= nil then -- "ArrayRemove" listeners
			for _, listener in ipairs(listeners[6]) do
				listener(index, old_value)
			end
		end
	end
	-- Raw listeners:
	for _, listener in ipairs(replica._raw_listeners) do
		listener("ArrayRemove", path_array, index, old_value)
	end
	return old_value
end
