-- a container item defines a 'container' structure listing its
-- inventories and their properties. a container object is created
-- in order to interact with a container
local lib = starlit.mod.lib
starlit.item.container = lib.class {
	__name = 'starlit:container';
	construct = function(stack, inv, def)
		local T,G = lib.marshal.t, lib.marshal.g
		local cdef = stack:get_definition()._starlit.container;
		local sd = {}
		for k,v in pairs(cdef.list) do
			sd[k] = {
				key  = v.key;
				type = T.inventoryList;
			}
		end
		return {
			stack = stack, inv = inv, pdef = def, cdef = cdef;
			store = lib.marshal.metaStore(sd)(stack);
		}
	end;
	__index = {
		slot = function(self, id)
			return string.format("%s_%s", self.pdef.pfx, id)
		end;
		clear = function(self) -- initialize or empty the metadata
			self:update(function()
				for k,v in pairs(self.cdef.list) do
					if v.sz > 0 then
						self.store.write(k, {})
					end
				end
			end)
		end;
		list = function(self, k) return self.store.read(k) end;
		read = function(self)
			local lst = {}
			for k,v in pairs(self.cdef.list) do
				if v.sz > 0 then lst[k] = self:list(k) end
			end
			return lst
		end;
		pull = function(self) -- align the inventories with the metadata
			for k,v in pairs(self.cdef.list) do
				if v.sz > 0 then
					local stacks = self:list(k)
					local sid    = self:slot(k)
					self.inv:set_size(sid, v.sz)
					self.inv:set_list(sid, stacks)
				end
			end
		end;
		update = function(self, fn)
			local old = ItemStack(self.stack)
			if fn then fn() end
			if self.cdef.handle then
				self.cdef.handle(self.stack, old)
			end
		end;
		push = function(self) -- align the metadata with the inventories
			self:update(function()
				for k,v in pairs(self.cdef.list) do
					if v.sz > 0 then
						local sid = self:slot(k)
						local lst = self.inv:get_list(sid)
						self.store.write(k, lst)
					end
				end
			end)
		end;
		drop = function(self) -- remove the inventories from the node/entity
			for k,v in pairs(self.cdef.list) do
				local sid = self:slot(k)
				self.inv:set_size(sid, 0)
			end
		end;
		slotAccepts = function(self, lst, slot, stack)
		end;
	};
}

function starlit.item.container.dropPrefix(inv, pfx)
	local lists = inv:get_lists()
	for k,v in pairs(lists) do
		if #k > #pfx then
			if string.sub(k, 1, #pfx + 1) == pfx .. '_' then
				inv:set_size(k, 0)
			end
		end
	end
end
