--===================================================
--									
--								GHI Item Data Transfer
--							GHI_ItemDataTransfer.lua
--
--	Syncronisation and transfering of item data betweet clients
--	
-- 						(c)2012 The Gryphonheart Team
--								All rights reserved
--===================================================

local class;
function GHI_ItemDataTransfer()
	if class then
		return class;
	end
	class = GHClass("GHI_ItemDataTransfer");

	local itemInfoList = GHI_ItemInfoList();
	local dynamicActionList = GHI_DynamicActionList();
	local comm = GHI_Comm();
	local log = GHI_Log();
	--local itemUpdater = GHI_ItemUpdater(); -- This is most likely not needed anymore
	local recieveItemFeedbackFunc = {};

	class.AddRecieveDataItemFeedbackFunction = function(func)
		table.insert(recieveItemFeedbackFunc, func);
	end

	class.SyncItemLinkData = function(player, guid)
		local item = itemInfoList.GetItemInfo(guid)
		local version, _ = item.GetVersions();
		comm.Send("ALERT", player, "ItemVersion", guid, version);
	end

	local recieveItemDataRequest = function(player, guid, ...)
		local item = itemInfoList.GetItemInfo(guid)
		local data = item.Serialize("link");
		comm.Send(nil, player, "ItemData", guid, data)
	end
	comm.AddRecieveFunc("ItemDataRequest", recieveItemDataRequest);

	local recieveItemVersion = function(player, guid, version, ...)
		local item = itemInfoList.GetItemInfo(guid)
		local ownVersion = 0;
		if item then
			ownVersion = item.GetVersions();
		end
		if ownVersion < version then
			comm.Send("ALERT", player, "ItemDataRequest", guid);
		elseif ownVersion > version then
			recieveItemDataRequest(player, guid);
		else
			for _, f in pairs(recieveItemFeedbackFunc) do
				f(player, guid, false);
			end
		end
	end
	comm.AddRecieveFunc("ItemVersion", recieveItemVersion);

	local recieveItemData = function(player, guid, data, ...)
		if not (data.guid) then
			data.guid = guid;
		end
		local recievedItem = GHI_ItemInfo(data);

		local itemGotUpdated = itemInfoList.UpdateItem(recievedItem);

		for _, f in pairs(recieveItemFeedbackFunc) do
			f(player, guid, itemGotUpdated);
		end
	end
	comm.AddRecieveFunc("ItemData", recieveItemData);

	class.SyncItemActionData = function(player, guid)
		class.SyncItemLinkData(player, guid);
		local item = itemInfoList.GetItemInfo(guid)
		local _, version = item.GetVersions();
		comm.Send("ALERT", player, "ItemActionVersion", guid, version, 1);
	end

	local recieveItemActionVersion = function(player, guid, version, format,...)
		local actionFormat = "oldAction";
		if format == 1 then
			actionFormat = "action";
		end

		local item = itemInfoList.GetItemInfo(guid)
		if item then
			local _, ownVersion = item.GetVersions();
			if ownVersion > version then
				local data = item.Serialize(actionFormat);

				-- split "rightClick" away from the rest of the data
				local rcData = data.rightClick;
				local otherData = {};
				for i, v in pairs(data) do
					if not (i == "rightClick") then
						otherData[i] = v;
					end
				end

				comm.Send("BULK", player, "ItemActionData", guid, rcData, otherData);
				comm.Send("ALERT", player, "ExpectItemActionData", guid, comm.GetQueueSize());

			elseif ownVersion < version then
				class.SyncItemActionData(player, guid);
			else
				log.Add(3, "Item action request unhandled. Versions are identical.", { guid = guid, version = version, ownVersion = ownVersion });
			end
		else
			log.Add(3, "Item action request unhandled. Item unknown.", { guid = guid, version = version });
		end
	end
	comm.AddRecieveFunc("ItemActionVersion", recieveItemActionVersion);

	local awaitingActionData = {};

	local recieveItemActionData = function(player, guid, rcData, otherData, ...)
		local data = otherData or {};
		data.rightClick = rcData;
		awaitingActionData[guid] = nil;
		local item = itemInfoList.GetItemInfo(guid);

		local currentData = item.Serialize("link");
		for i,v in pairs(data) do
			currentData[i] = v;
		end
		local newItem = GHI_ItemInfo(currentData);

		local itemGotUpdated = itemInfoList.UpdateItem(newItem)

		if itemGotUpdated then
			local dependingItems = newItem.GetDependingItems();
			for _, dependingGuid in pairs(dependingItems) do
				class.SyncItemLinkData(player, dependingGuid);
				class.SyncItemActionData(player, dependingGuid);
			end

			if newItem.GetItemComplexity() == "advanced" then
				local set = newItem.GetDynamicActionSet();
				if set then
					local guids = set.GetInstanceGuids();
					for _,daGuid in pairs(guids) do
						dynamicActionList.SyncDynamicAction(player,daGuid);
					end
				end
			end

		end
	end
	comm.AddRecieveFunc("ItemActionData", recieveItemActionData);

	local recieveExpectItemActionData = function(player, guid, queueSize, ...)
		if queueSize and queueSize > 5000 then
			awaitingActionData[guid] = (queueSize / 250) + time();
		else
			awaitingActionData[guid] = nil;
		end
	end
	comm.AddRecieveFunc("ExpectItemActionData", recieveExpectItemActionData);

	local recieveDependingItemData = function(player, guid, dependData, ...)
	--To add in later
	end

	return class;
end

