
local onEpilogue = nil;
if string.find(string.lower(GetRealmName()),"epilogue") then
	onEpilogue = true;
end

--GHI = LibStub("AceAddon-3.0"):new("GHI","AceComm-3.0", "AceSerializer-3.0",...);
GHI = LibStub("AceComm-3.0");
local serial = LibStub("AceSerializer-3.0");

function GHI:SendMessage(channel, player, ...)
	GHI:SendCommMessage("GHI", serial:Serialize({...}), channel, player);
end

function GHI:SendPrioritizedMessage(prio, channel, player, ...)
	GHI:SendCommMessage("GHI", serial:Serialize({...}), channel, player, prio);
end

function GHI_CommunicationHookings()
	
	--this:RegisterEvent("CHAT_MSG_ADDON");
	
	GHI:RegisterComm("GHI", function(...) GHI:RecieveRawMessage(...) end)
	
	-- SendCommMessage
	
	--[[
	GHI.Orig_SendCommMessage = GHI.SendCommMessage;
	GHI.SendCommMessage = function(self,channel, player, ...)
	GHI.SendCommMessage = function(self,channel, player, ...)
		GHI.Orig_SendCommMessage(self,"GHI",serial:Serialize({...}),channel,player);
	end 
	GHI.SendPrioritizedCommMessage = function(self,prio,channel, player, ...)
		GHI.Orig_SendCommMessage(self,"GHI",serial:Serialize({...}),channel,player,prio);
	end -- ]]
	
	orig_MainMenuBarPerformanceBarFrame_OnEnter = MainMenuBarPerformanceBarFrame_OnEnter;
	MainMenuBarPerformanceBarFrame_OnEnter = GHI_MainMenuBarPerformanceBarFrame_OnEnter;
	
	
	
	
end

--[[	
Heave Comm in GHI:
	Item data
	Buff data

]]
if GHI then
	GHI.ownName = UnitName("player");
end 

function GHI:ReceiveMessageFromChannel(prefix, sender, distribution, dummy, recieverName, oldRecieve, ...)  -- 
	--[[
	local reciever = "dummy"
	if type(meta) == "string" then
		GHI_Message("FROM CHANNEL. "..prefix.." : ".. sender.." : "..distribution.." : "..recieverName.." :  ".. meta.." : "..type(arg1).." : "..type(arg2))
	else
		GHI_Message("FROM CHANNEL. "..prefix.." : ".. sender.." : "..distribution.." : "..recieverName.." :  ".. type(meta).." : "..type(arg1).." : "..type(arg2))
	end   --]]
	--local meta, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12 = unpack({...});
	--GHE:Msg("FROM CHANNEL. prefix: %s, sender: %s, distribution: %s, dummy: %s, oldRecieve: %s, recieverName: %s, meta: %s, arg1: %s,arg2: %s, arg3: %s, arg4: %s",prefix, sender, distribution,dummy, oldRecieve, recieverName, ...)
	--GHE:Msg("if %s == %s then",recieverName,GHI.ownName);
	if recieverName == nil then
		GHI_Message((sender or "Unknown").."'s client is sending data without any target.");
	end
	
	assert(not(recieverName==nil),"A client is sending data without any target.");
	local t = {...};
	t=GHI.UnpackLen13(t);

	if recieverName == GHI.ownName then
		GHI:ReceiveMessage(prefix, sender, distribution,oldRecieve, unpack(t))
	end
end

--  End of epilogue edits

--	====================================  Ace
function GHI:RecieveRawMessage(prefix,text,distribution,sender)
	local sucess, t = serial:Deserialize(text);
	GHI:ReceiveMessage(prefix, sender, distribution, unpack(t));
end

local recieveFunctions = {};
function GHI:RegisterRecieve(tag,func)
	assert(type(tag) == "string" and type(func) == "function","RegisterRecieve usage: tag (string), func (function)");
	assert(not(type(recieveFunctions[tag])=="function"),"Tag "..tag.." already registered.");
	recieveFunctions[tag] = func;
end


GHI_ShowComm = false;
function GHI:ReceiveMessage(prefix, sender, distribution, oldRecieve, meta, arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12)
	--[
	if GHI_ShowComm == true then
		if type(meta) == "string" then
			GHI_Message(prefix.." : ".. sender.." : ".. distribution.." :  ".. meta.." : "..type(arg1).." : "..type(arg2))
		else
			GHI_Message(prefix.." : ".. sender.." : ".. distribution.." :  ".. type(meta).." : "..type(arg1).." : "..type(arg2))
		end 
	end
	
	if oldRecieve == true then
		GHI_RecieveData(meta,arg1,sender)
	elseif oldRecieve == false then
		if meta == "BuffInfo" then
			GHI_RevieveBuff(sender,arg1);
		elseif meta == "DebuffInfo" then
			GHI_RevieveDebuff(sender,arg1);
		elseif meta == "ItemVersion" then
			GHI_RecieveItemVersion(arg1,arg2,sender);
		elseif meta == "ItemDataRequest" then
			GHI_RecieveItemDataRequest(arg1,sender);
		elseif meta == "ItemData" then
			GHI_RecieveItemData(arg1,arg2,sender);
		elseif meta == "SuspectedLinkName" then
			GHI_SendLink(arg1,sender);
		elseif meta == "ItemDataVersions" then
			GHI_ItemDataVersions(arg1,arg2,arg3,sender) 
		elseif meta == "ItemRCData" then
			GHI_RecieveItemRCData(arg1,arg2);
		elseif meta == "ExpectRCData" then
			GHI_RecieveExpectRCData(arg1,nil);
		elseif meta == "ExpectRCDataTime" then
			GHI_RecieveExpectRCData(arg1,arg2);
		elseif meta == "EndRCData" then
			GHI_RecieveEndRCData(arg1);
		elseif meta == "TradeDuration" then
			GHI_RecieveTradeDuration(arg1,arg2,arg3,arg4);
		elseif meta == "ApplyBuff" then		
			ApplyGHIBuff(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)
		elseif meta == "TradeBagInfo" then	
			GHI_RecieveTradeBagDetails(arg1,arg2);
		end
	
	end
	
	if string.len(meta or "") > 0 and type(recieveFunctions[meta]) == "function" then
		recieveFunctions[meta](sender,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9);
	end
end


--	==================================== Communication	====================================

GHI_In = 0;
GHI_Out = 0;
GHI_InThisSec = 0;
GHI_OutThisSec = 0;
GHI_OutThisSec = 0;

GHI_COMMUNICATION_LIMIT = 20;

GHI_OutBuffer = {};
GHI_OutPointer = 0;

function GHI_SendDataToBuffer(metaData,data,reciever)
	--- should no longer be used
	
	
	--GHR_Message("GHI. In: "..GHI_In.." Out: "..GHI_Out);
	--GHI_Message("=== Sending Data to "..reciever.." ===");
	if reciever == "" or reciever == nil then return end;
	
	local a = strsub(reciever,0,1);
	local b = strsub(reciever,2);
	local new = "";
	
	if a then
		local va = tonumber(strbyte(a));
		if (va >= 65 and va <= 90) or (va >= 97 and va <= 122) then
			new = strupper(a)..strlower(b);
		else 
			new = reciever;
		end
	end
	
	if new == nil or new == "" or new == " " then return end;
	
	
	
	--GHR_Message("Sending to "..new);
	--GHI_Message(metaData);
	--SWM_Message(data);

	
	
	GHI_OutThisSec = GHI_OutThisSec + 1;
	
	if GHI_OutThisSec > GHI_COMMUNICATION_LIMIT or GHI_OutPointer > 0 then    --- 	or  buffer size > 0
		local list = {};
		list.metaData = metaData;
		list.data = data;
		list.reciever = new;
		
		GHI_OutPointer = GHI_OutPointer + 1;
		GHI_OutBuffer[GHI_OutPointer] = list;
	else
		GHI_Out = GHI_Out + 1;
		SendAddonMessage("GHI_"..metaData,data,"WHISPER",new);
	end
end

function GHI_SendBufferData()
	if GHI_OutPointer == 0 then return end
	
	-- 	Move data in buffer
	local firstNil = 0;
	if GHI_OutPointer > 500 then
		for i = 1,GHI_OutPointer do
			if GHI_OutBuffer[i] == nil then
				firstNil = i;
				break;
			end
		end
	end
	if not(firstNil == 0) then
		local addr = 0;
		for i = firstNil,GHI_OutPointer do
			addr = addr + 1;
			GHI_OutBuffer[addr] = GHI_OutBuffer[i];
		end
		GHI_OutPointer = addr;
	end
	
	
	local c1 = 0;
	local c2 = 0;
	local c3 = GHI_OutPointer;
	local send = GHI_OutThisSec;
	if GHD_OutThisSec == nil then
		GHD_OutThisSec = 0;
	end
	for i = 1,GHI_OutPointer do
		if send + GHD_OutThisSec > GHI_COMMUNICATION_LIMIT then
			break;
		end
		
		if type(GHI_OutBuffer[i]) == "table" then
			local metaData = GHI_OutBuffer[i].metaData;
			local data = GHI_OutBuffer[i].data;
			local reciever = GHI_OutBuffer[i].reciever;
			if not(metaData == nil) and not(reciever == nil) then
				GHI_Out = GHI_Out + 1;
				SendAddonMessage("GHI_"..metaData,data,"WHISPER",reciever);
				send = send + 1;

				
				GHI_OutBuffer[i] = nil;
				
				if c1 == 0 then
					c1 = i;
				end
			end
		end
		if i == GHI_OutPointer then
			GHI_OutPointer = 0;
			break;
		end
		c2 = i;
	end
	
	--GHI_Message("Sending GHI buffer. Address: "..c1.." - "..c2.." Total: "..c2 - c1.." Max: "..c3);
	
end







function GHI_SendData(dataType,data,reciever)
	if reciever == "" or reciever == nil then return end;
	
	local a = strsub(reciever,0,1);
	local b = strsub(reciever,2);
	local new = "";
	
	if a then
		local va = tonumber(strbyte(a));
		if (va >= 65 and va <= 90) or (va >= 97 and va <= 122) then
			new = strupper(a)..strlower(b);
		else 
			new = reciever;
		end
	end
	
	if new == nil or new == "" or new == " " then return end;

	GHI:SendMessage("WHISPER",new, true, dataType, data)
	--SendAddonMessage("GHI_"..dataType,data,"WHISPER",new);
end

function GHI_RecieveData(b,data,sender)
		
	data = GHI_ConvertToNum(data);
	--GHI_Message("Recieved "..b);
	if b == "ReqLink" then
		GHI_SendLink(data,sender)
	elseif string.sub(b,0,10) == "ItemReply<" then
		GHI_RecieveLink(string.sub(b,10),data,sender);
	elseif string.sub(b,0,12) == "ItemReplyEnd" then
		GHI_RecieveLinkEnd(data,sender);
	elseif string.sub(b,0,6) == "Trade<" then	
		GHI_RecieveTradeItem(string.sub(b,7),data,sender);
	elseif b == "TradeAccepted" then
		if sender == GHI_TradePlayer then
			GHI_AcceptTrade();
		end
	elseif b == "RequestBuffs" then	
		GHI_SendBuffInfo(sender,data)
		GHI_SendDebuffInfo(sender,data)
	elseif string.sub(b,0,5) == "Buff_" then	
		--GHI_RecieveBuff(string.sub(b,6),data,sender);
	elseif b == "RequestDebuffs" then	
		GHI_SendDebuffInfo(sender)
	elseif string.sub(b,0,7) == "Debuff_" then	
		GHI_RecieveDebuff(string.sub(b,8),data,sender);
	elseif string.sub(b,0,15) == "ItemDataVersion" then
		GHI_RecieveItemDataVersion(data,sender);
	elseif b == "AddonVersionReq" then
		local ver = GetAddOnMetadata("GHI", "Version");
		GHI_SendData("AddonVersionAnswer",ver,sender);
		--GHI_SendData("AddonBetaAnswer",GHI_BetaKey,sender);
	elseif b == "AddonVersionAnswer" then
		if sender == GHI_TradePlayer then
			GHI_RecipientHasGHI = true;
			GHI_RecipientGHIVersion = data;
		end
		if sender == GHI_PingedPlayer then
			GHI_RecievePing(sender,data);
		end
		--GHI_Message(sender.." got version "..data);
	elseif b == "AddonBetaAnswer" then
		if sender == GHI_PingedPlayer then
			GHI_Message(data);
			GHI_PingedPlayer = nil;
		end
	elseif b == "AreaSound" then
	 GHI_GetAreaEffectSound(sender,data)
	  ---i am gonna split the sound and debuff into thier own functions.
	  --print("area sound");
	elseif b == "AreaBuff" then
	GHI_GetAreaEffectBuff(sender,data)
	elseif b == "DisableGHI" then
		GHI_MiscData["disabled"] = true;
	elseif b == "EnableGHI" then
		GHI_MiscData["disabled"] = false;
	end
end



--	vvvvvvvvv	Item data transfer

function GHI_SendLink(name,player) 
	--	Should be run backwards?
	local found = false;
	if not(type(GHI_ItemData) == "table") then return; end
	
	--GHI_Message("Request: "..name.." to "..player);
	
	for index1,value1 in pairs(GHI_SendItemsID) do 
		if GHI_IsOfficialItem(value1) then
			value1 = tonumber(value1);
			if type(GHI_OfficialItemData[value1]) == "table" then 
				if GHI_OfficialItemData[value1].name == name then
					local version = GHI_GetVersions(value1);
					GHI:SendPrioritizedMessage("ALERT","WHISPER",player,false,"ItemVersion",value1,0)
					found = true;
					break;
				end
			end
		else
			if type(GHI_ItemData[value1]) == "table" then
				if GHI_ItemData[value1].name == name then
					local version = GHI_GetVersions(value1);
					GHI:SendPrioritizedMessage("ALERT","WHISPER",player,false,"ItemVersion",value1,version)
					found = true;
					break;
				end
			end
		end
	end
	
	if found == false then
		for i = 1,#(GHI_SendNotItems) do
			if GHI_SendNotItems[i] == name then
				GHI:SendPrioritizedMessage("ALERT","WHISPER",player,false,"ItemVersion","0_"..name,0)
				found = true;
				--GHI_Message("Send none link");
				break;
			end
		end
	end
	
end

function GHI_RecieveItemVersion(ID,version,sender)
	if ID and string.sub(ID,0,2) == "0_" then
		--GHI_Message("Recieve none link");
		GHI_RecieveLinkEnd(ID,sender);
	end
	if GHI_IsOfficialItem(ID) then
		GHI_RecieveLinkEnd(ID,sender)
	end
	local ownVersion = GHI_GetVersions(ID);
	--GHI_Message("sender-> "..version.." > "..ownVersion.." <- own")
	if version > ownVersion then
		GHI:SendMessage("WHISPER",sender,false,"ItemDataRequest",ID)
		GHI_RecieveExpectLink(sender);
	else
		GHI_RecieveLinkEnd(ID,sender)
	end

end

function GHI_RecieveItemDataRequest(ID,sender)
	if not(type(GHI_ItemData) == "table") or not(type(GHI_ItemData[ID])=="table") then return end
	
	local data = {};
	for index1,value1 in pairs(GHI_ItemData[ID]) do
		if not(index1 == "rightClick") then
			data[index1] = value1;
		
		end	
	end
	
	
	GHI:SendMessage("WHISPER",sender,false,"ItemData",ID,data)
end

function GHI_RecieveItemData(ID,data,sender)
	local origRC = GHI_GetRightClickInfo(ID);
	
	GHI_ItemData[ID] = data;
	GHI_SetRightClickInfo(ID,origRC);
	GHI_RecieveLinkEnd(ID,sender)
	--GHI_Message("GHI_RecieveItemData version: "..(GHI_ItemData[ID].version or "nil"));
end


function GHI_RecieveLink(prefix,data,sender)  -- no longer in use
	--GHI_Message(prefix.." : "..data);
	
	local arrayName = "GHI_ItemData";
	local array;
	array = getglobal(arrayName);
	if not(type(array) == "table") then  return end;
	
	
	addrPart = prefix;
	
	
	if data == tostring(tonumber(data)) then data = tonumber(data); end
	
	c = string.find(addrPart,"<");
	d = string.find(addrPart,">");
	
	if c and d then
		addr1 = string.sub(addrPart,c+1,d-1);
		
		if addr1 then 
			if addr1 == tostring(tonumber(addr1)) then addr1 = tonumber(addr1); end
			c = string.find(addrPart,"<",d);
			d = string.find(addrPart,">",d+1);
			if c and d then
				addr2 = string.sub(addrPart,c+1,d-1);
				
				if addr2 then 
					if addr2 == tostring(tonumber(addr2)) then addr2 = tonumber(addr2); end
					c = string.find(addrPart,"<",d);
					d = string.find(addrPart,">",d+1);
					if c and d then
						addr3 = string.sub(addrPart,c+1,d-1);
						if addr3 then 
							if addr3 == tostring(tonumber(addr3)) then addr3 = tonumber(addr3); end
							c = string.find(addrPart,"<",d);
							d = string.find(addrPart,">",d+1);
							if c and d then
								addr4 = string.sub(addrPart,c+1,d-1);
								if addr4 then
									if addr4 == tostring(tonumber(addr4)) then addr4 = tonumber(addr4); end
									if not(type(array[addr1]) == "table") then
										array[addr1] = {}
									end
									if not(type(array[addr1][addr2]) == "table") then
										array[addr1][addr2] = {}
									end
									if not(type(array[addr1][addr2][addr3]) == "table") then
										array[addr1][addr2][addr3] = {}
									end
									array[addr1][addr2][addr3][addr4] = data;
									setglobal(arrayName,array);
								end
							else
								if not(type(array[addr1]) == "table") then
									array[addr1] = {}
								end
								if not(type(array[addr1][addr2]) == "table") then
									array[addr1][addr2] = {}
								end
								array[addr1][addr2][addr3] = data;
								setglobal(arrayName,array);
							end
						end
					else
						if not(type(array[addr1]) == "table") then
							array[addr1] = {}
						end
						array[addr1][addr2] = data;
						setglobal(arrayName,array);
						
					end
				end
			else
				array[addr1] = data;
				setglobal(arrayName,array);
			end		
		end
	end	
	
end


GHI_ExpectLink = {};

function GHI_RecieveExpectLink(sender)
	if sender then
		GHI_ExpectLink[sender]=time();
		--GHR_Message("Expect link from "..sender);
	end
end

function GHI_RecieveLinkEnd(data,sender)
	--GHR_Message("Recieve link end "..data.." from "..sender);
	local info;
	if data and string.sub(data,0,2) == "0_" then
		info = {};
		info.notLink = true;
		info.name = string.sub(data,3);
	elseif GHI_IsOfficialItem(data) then
		data = tonumber(data);
		info = GHI_OfficialItemData[data];
		
	else
		info = GHI_ItemData[data];
	end
	if not( type(info) == "table") then return end;
	
	
	
	for index1,value1 in pairs(GHI_IncMsgWaiting) do 
		if type(value1) == "table" then
			
			if value1.sender == sender  then
				local text = value1.text;
				a = 0;
				done = true;
				for i=1,5 do
					--GHI_Message("link "..i.." string is now '"..text.."' Size: "..strlen(text));
					a = GHI_SearchStringForChar(text,91,a+1);
					b = strfind(text,"]",a);
					if a and b then
						
						local linkText,link;
						linkText = strsub(text,a+1,b-1);
						
						--GHI_Message(linkText.." == "..info.name..". a found as: "..a);
						if info.notLink == true and info.name == linkText then
							--GHI_Message("Found as "..a..": "..info.name);
							text = strsub(text,0,a-1).."|nolink["..linkText.."]"..strsub(text,b+1);
							a = a + 16;
						elseif linkText == info.name then
							link = GHI_GenerateLink(data);
							local cc = strlen(text);
							text = strsub(text,0,a-1)..link..strsub(text,b+1);
							--GHR_Message("Expanded with "..strlen(text)-cc);
							--GHR_Message("Insert "..link);
							a = a + 60;
						else
							-- is it an already inserted link?
							
							c = string.sub(text,a-7,a-1);
							
							--GHI_Message("'"..c.."' lenght: "..strlen(c).."   link text: "..linkText);
							if not(c == "0:0:0|h" or c == "|nolink") then   -- not already inserted
								---GHR_Message("not already inserted");
								done = false;
							end
							a = a + 2;
						end
						
						--c,d = strfind(text,linkText);
						
						--GHI_SendDataToBuffer("ReqLink",strsub(text,a+1,b-1),arg2);
						
						--
						
					else 	
						break;
					end
				end
				
				a = 0;
				for i = 1,5 do 
					a = GHI_SearchStringForChar(text,91,a+1);
					b = strfind(text,"]",a);
					if a and b then
						c = string.sub(text,a-7,a-1);
						--GHI_Message(c.." == 0:0:0|h");
						if not(c == "0:0:0|h" or c == "|nolink") then
							done = false;
							--GHI_Message("not done: "..text);
						end
						
					else
						break;
					end
				end
				
				
				
				if done == true then
					--GHI_Message("text: "..text);
					text = gsub(text,"|nolink","");
					local old_arg1 = arg1;  --
					local event = value1.event;
					setglobal("arg1", text);  --GHI_Message("arg1: "..(text or "nil"));
					setglobal("arg2", value1.sender); --GHI_Message("arg2: "..(value1.sender or "nil"));
					setglobal("arg3", value1.arg3); --GHI_Message("arg3: "..(value1.arg3 or "nil"));
					setglobal("arg4", value1.arg4); --GHI_Message("arg4: "..(value1.arg4 or "nil"));
					setglobal("arg5", value1.arg5); --GHI_Message("arg5: "..(value1.arg5 or "nil"));
					setglobal("arg6", value1.arg6); --GHI_Message("arg6: "..(value1.arg6 or "nil"));
					setglobal("arg7", value1.arg7); --GHI_Message("arg7: "..(value1.arg7 or "nil"));
					setglobal("arg8", value1.arg8); --GHI_Message("arg8: "..(value1.arg8 or "nil"));
					setglobal("arg9", value1.arg9); --GHI_Message("arg9: "..(value1.arg9 or "nil"));
					setglobal("arg10", value1.arg10); --GHI_Message("arg10: "..(value1.arg10 or "nil"));
					setglobal("arg11", value1.arg11); 
					setglobal("arg12", value1.arg12); 
					setglobal("arg13", value1.arg13); 
					setglobal("arg14", value1.arg14); 
					setglobal("arg15", value1.arg15); 
					setglobal("arg16", value1.arg16); 
					setglobal("arg17", value1.arg17); 
					setglobal("arg18", value1.arg18); 
					setglobal("arg19", value1.arg19); 
					setglobal("this", value1.this); --GHI_Message("this: "..(value1.this:GetName() or "nil"));
					setglobal("event", value1.event); --GHI_Message("event: "..(value1.event or "nil"));
					GHI_TestTrigger = true;
					----------------  start test
					--[[
					GHI_Message("Recieved link end. Variable list: ");
					for i=1,11 do
						local V = getglobal("arg"..i);
						if type(V) == "string" or type(V) == "number" then
							GHI_Message("arg"..i..": "..type(V).." = "..V);
						else
							GHI_Message("arg"..i..": "..type(V));
						end
					end
					local V = getglobal("this");
					if type(V) == "string" or type(V) == "number" then
						GHI_Message("this: "..type(V).." = "..V);
					else
						GHI_Message("this: "..type(V));
					end
					local V = getglobal("event");
					if type(V) == "string" or type(V) == "number" then
						GHI_Message("event: "..type(V).." = "..V);
					else
						GHI_Message("event: "..type(V));
					end]]
					--------------   end test
					
					
					if GHI_CompAddons["Prat"] == true and not(value1.FCCC == true) then 
						if event == "CHAT_MSG_CHANNEL" then
							for i = 1,7 do
								setglobal("this", getglobal("ChatFrame"..i));
								--Prat:ChatFrame_MessageEventHandler(event)
								if i == 1 then
									Prat:ChatFrame_MessageEventHandler(event);
								else
									GHI_origChatFrame_MessageEventHandler(getglobal("ChatFrame"..i),event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15,arg16,arg17,arg18,arg19);
								end
							end	
						else
							-- todo: run for other chat windows
							Prat:ChatFrame_MessageEventHandler(event)
						end
						
					elseif GHI_CompAddons["ForgottenChatCC"] == true and value1.FCCC == true then
						if value1.self == true then
							GHI_OrigFCCC_OutgoingMessage(value1.to, text, value1.lan)
						else
							GHI_OrigFCCC_IncomingMessage(value1.sender, text, value1.afk)
						end
					else
						if event == "CHAT_MSG_CHANNEL" then
							for i = 1,7 do
								setglobal("this", getglobal("ChatFrame"..i));
								GHI_origChatFrame_MessageEventHandler(getglobal("ChatFrame"..i),event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,arg15,arg16,arg17,arg18,arg19);
							end		
						else
							-- todo: run for other chat windows
							GHI_origChatFrame_MessageEventHandler(value1.self,event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,arg15,arg16,arg17,arg18,arg19);
						end
					end
					
					GHI_IncMsgWaiting[index1] = nil;
					setglobal("arg1", old_arg1);
					GHI_IsForcingEvent = false;
				else
					GHI_IncMsgWaiting[index1].text = text; --GHI_Message("Msg still stored: "..text);
				end			
			end
		end
	end
	
	--	Check if the item is in the trade window
	for i = 1,6 do
		if type(GHI_TradeItemsRecipient[i]) == "table" then
			if GHI_TradeItemsRecipient[i].ID == data then
				GHI_SetRecipientButton(i,GHI_TradeItemsRecipient[i].ID,GHI_TradeItemsRecipient[i].amount)
			end
		end
	end
end


function GHI_ItemDataVersions(ID,v1,v2,sender) --- after trade
	local own_v1,own_v2 = GHI_GetVersions(ID);
	if own_v1 > v1 then
		GHI_RecieveItemDataRequest(ID,sender)
	end
	if own_v2 > v2 then
		if not(type(GHI_ItemData) == "table") or not(type(GHI_ItemData[ID])=="table") then return end
	
		local data = {};
		for index1,value1 in pairs(GHI_ItemData[ID]) do
			if (index1 == "rightClick") then
				data = value1;
			
			end	
		end
		
		-- todo:  Send an alert with expectation of the information
		GHI:SendPrioritizedMessage("ALERT","WHISPER",sender,false,"ExpectRCData",ID)
		
		local size_b = 0;
		for prioname, Prio in pairs(ChatThrottleLib.Prio) do
			if type(Prio.Ring)=="table" and type(Prio.Ring.pos)=="table" then
				for prioname, data in pairs(Prio.Ring.pos) do
					size_b = size_b + (data.nSize or 0);
				end
			end
		end
		
		GHI:SendMessage("WHISPER",sender,false,"ItemRCData",ID,data)
		
		
		local size_a = 0;
		for prioname, Prio in pairs(ChatThrottleLib.Prio) do
			if type(Prio.Ring)=="table" and type(Prio.Ring.pos)=="table" then
				for prioname, data in pairs(Prio.Ring.pos) do
					size_a = size_a + (data.nSize or 0);
				end
			end
		end
		
		
		
		--GHI_Message("before: "..size_b.." after: "..size_a);
		--local a = ChatThrottleLib:UpdateAvail(); 
		-- TODO. calculate queue time with corect bandwith. Calculate sending time.
		local secs = (size_a)/250; -- assumed average
		--GHI_Message("done in "..secs.." secs");
		GHI:SendPrioritizedMessage("ALERT","WHISPER",sender,false,"ExpectRCDataTime",ID,secs)
		
		
		GHI:SendMessage("WHISPER",sender,false,"EndRCData",ID)
	end
	
	
end

GHI_AwaitingRCData = {};
GHI_AwaitingRCDataTime ={};

function GHI_RecieveExpectRCData(ID,Time)
	GHI_AwaitingRCData[ID] = true;
	if Time then
		GHI_AwaitingRCDataTime[ID] = Time+time();
	else
		GHI_AwaitingRCDataTime[ID] = Time;
	end
end

function GHI_RecieveItemRCData(ID,data)
	if not(type(GHI_ItemData) == "table") or not(type(GHI_ItemData[ID])=="table") then return end
	GHI_ItemData[ID].rightClick = data;
	--GHI_Message("GHI_RecieveItemRCData version: "..(GHI_ItemData[ID].version or "nil"));
end

function GHI_RecieveEndRCData(ID)
	GHI_AwaitingRCData[ID] = nil;
	GHI_AwaitingRCDataTime[ID] = nil;
end


--	^^^^^^^^^^^^
---AREA SOUND/BUFFS
local function round(number, decimals)
    return (("%%.%df"):format(decimals)):format(number)
end

local function XYUpdate()
local x, y =GetPlayerMapPosition("player");
local xa = math.modf(x*1000)/10;
local ya = math.modf(y*1000)/10;
x = round(x*1002,2);
y = round(y*668,2);
WorldMapFrame:Hide();

return x,y;
end

local SOUND_PLAYED = false;

function UpdateLastPlayed()

--local lastsound = sound or lastsound;

if SOUND_PLAYED == false then--my logic is off in the following but eh
SOUND_PLAYED = true;
--START A DELAY TIMER
GHI_EachMin()--delay and wait then set to false.

else
--reset value as timer would have to call this again or we reset from timer
SOUND_PLAYED = false;
end

end

function GHI_SendAreaEffect(typed,...)
local zone = GetSubZoneText();
local x,y = XYUpdate();
--print(typed)
if typed == "Sound" then

	local soundPath,range = ...;
	local comzone = GetZoneText()
     --print(soundPath);
	id, name = GetChannelName("General - "..comzone);--this is how the api sees the zone name. General - Zone.
	 if (id > 0 and name ~= nil) then
	   --get the proper index..stupid API
	    id = id + 2; --group and raid are hidden but are indexs one and 2 so hopefully adding two to the 
					--returned ID should get thr right index, assuming general is channel 1.
	  memberCount = GetNumChannelMembers(id)

	  if (memberCount ~= nil) then
	    for j = 1, tonumber(memberCount) do
		   local MemberName = select(1, GetChannelRosterInfo(id, j));
--SendAddon message to member name with the soundpath,zone and the xy coords.
         local data = zone..":"..x..":"..y..":"..soundPath..":"..range;
		 --print(MemberName)
		 --print(data)
		
            GHI_SendData("AreaSound",data,MemberName)

		end
	  end

    end

elseif typed == "spell" then
--do as above but for buff/debuffs.
	local filter,refID,guid,name,description,icon,totalDuration,endTime,count,debuffType,range = ...;
	local comzone = GetZoneText()
--a varible contrant for all the buff info that comes from the ... part of the function

	id, name = GetChannelName("General - "..comzone);--this is how the api sees the zone name. General - Zone.
	if (id > 0 and name ~= nil) then
	 memberCount = GetNumChannelMembers(id)
	 if (memberCount ~= nil) then
	   for j = 1, tonumber(memberCount) do
	   local MemberName = select(1, GetChannelRosterInfo(id, j));
        GHI_SendData("AreaBuff",data,MemberName)
	   end
	  end
	end
end

end


function GHI_GetAreaEffectSound(sender,data)--... is other data.
if GHI_MiscData["block_area_sound"] then return end
local zone = GetSubZoneText();
local X,Y = XYUpdate();



local zonesender,sx,sy,soundPath,range = strsplit(":",data);

local range = range or 60;
--print(zonesender)
--NOTE:range now accepts numbers or "Zone" to broadcast to entire zone, maybe world with GHD?
if range~="Zone" then

if zone == zonesender then

if ( math.abs(math.sqrt((sx-X)*(sx-X) + (sy-Y)*(sy-Y))) <= range)and SOUND_PLAYED == false then
UpdateLastPlayed()---first call set to true
PlaySoundFile(soundPath);
   end
end
  
 else 
    UpdateLastPlayed()---first call set to true
    PlaySoundFile(soundPath);
end

end

function GHI_GetAreaEffectBuff(sender,data)

local filter,refID,guid,name,description,icon,totalDuration,endTime,count,debuffType,range = strsplit(":",data);

local zone = GetSubZoneText();
local X,Y = XYUpdate();
local range = range or 60;
if range~= "Zone" then

if zone == zonesender then

----I need to do some range math, someone help.
if (math.abs(math.sqrt((sx-X)*(sx-X) + (sy-Y)*(sy-Y)))<= range) and SOUND_PLAYED == false then
UpdateLastPlayed()--just gonna do this for buff delay too
local b = GHU_New("buff")
b:CastBuff(filter,refID,guid,name,description,icon,totalDuration,endTime,count,debuffType)
   end
   end
 else
 --zone broadcast
  UpdateLastPlayed()--just gonna do this for buff delay too
local b = GHU_New("buff")
b:CastBuff(filter,refID,guid,name,description,icon,totalDuration,endTime,count,debuffType)
 end
end





GHI_TimeOutLimit = 10;
function GHI_CheckTimeoutedMsg()
		
	
	for index1,value1 in pairs(GHI_IncMsgWaiting) do 
		if type(value1) == "table" then
			local sender = value1.sender;
			local delay = 0;
			if type(GHI_ExpectLink[sender]) == "number" then
				
				delay = GHI_TimeOutLimit*4
				
			end
		
			if value1.time < time() - (GHI_TimeOutLimit + delay) then
				
				
				--GHR_Message(value1.text.." from "..value1.sender.." timed out after ".. (GHI_TimeOutLimit + delay).." secs");
				local text = gsub(value1.text,"|nolink","");
				
				local event = value1.event;
				-- this should be done dynamically when making GHU_Links
				setglobal("arg1", text);
				setglobal("arg2", value1.sender);
				setglobal("arg3", value1.arg3);
				setglobal("arg4", value1.arg4);
				setglobal("arg5", value1.arg5);
				setglobal("arg6", value1.arg6);
				setglobal("arg7", value1.arg7);
				setglobal("arg8", value1.arg8);
				setglobal("arg9", value1.arg9);
				setglobal("arg10", value1.arg10);
				setglobal("arg11", value1.arg11);
				setglobal("arg12", value1.arg12);
				setglobal("arg13", value1.arg13);
				setglobal("arg14", value1.arg14);
				setglobal("arg15", value1.arg15);
				setglobal("arg16", value1.arg16);
				setglobal("arg17", value1.arg17);
				setglobal("arg18", value1.arg18);
				setglobal("arg19", value1.arg19);
				setglobal("this", value1.this);
				setglobal("self", value1.self);
				
				
				if GHI_CompAddons["Prat"] == true and value1.FCCC == false then 
					
					if event == "CHAT_MSG_CHANNEL" then
						for i = 1,7 do
							setglobal("this", getglobal("ChatFrame"..i));
							Prat:ChatFrame_MessageEventHandler(event)
						end		
					else
						-- todo: run for other chat windows
						Prat:ChatFrame_MessageEventHandler(event)
					end
				elseif GHI_CompAddons["ForgottenChatCC"] == true and value1.FCCC == true then
					if value1.self == true then
						GHI_OrigFCCC_OutgoingMessage(value1.to, value1.text, value1.lan)
					else
						GHI_OrigFCCC_IncomingMessage(value1.sender, value1.text, value1.afk)
					end
				else
					if event == "CHAT_MSG_CHANNEL" then
						for i = 1,7 do
							setglobal("this", getglobal("ChatFrame"..i));
							--GHI_origChatFrame_MessageEventHandler(value1.self,event);
							GHI_origChatFrame_MessageEventHandler(getglobal("ChatFrame"..i),event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,arg15, arg16, arg17, arg18, arg19);
						end		
					else
						-- todo: run for other chat windows
						GHI_origChatFrame_MessageEventHandler(value1.self,event,arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14,arg15, arg16, arg17, arg18, arg19);
					end
				end
				GHI_IncMsgWaiting[index1] = nil;
						
			end
		end
	end
	
	
	
end

--	======================== Sending item data
--	sending link = no right click info
--	Sending item data = inc right click info

function GHI_SendItemData(ID,player)
	if not(type(GHI_ItemData) == "table") then return; end
	
	--GHI_Message("Sending all data for "..ID.." to "..player);
	
	
	if type(GHI_ItemData[ID]) == "table" then
		
	local index1 = ID;
	
		for index2,value2 in pairs(GHI_ItemData[ID]) do 
			if type(value2) == "table" then
				for index3,value3 in pairs(value2) do 
					if type(value3) == "table" then
						for index4,value4 in pairs(value3) do 
							if type(value4) == "table" then
								-- More than 4 arrays
							else
								GHI_SendDataToBuffer("ItemReply<"..index1.."><"..index2.."><"..index3.."><"..index4..">",value4,player);
							end
						end
					else
						GHI_SendDataToBuffer("ItemReply<"..index1.."><"..index2.."><"..index3..">",value3,player);
					end
				end
			else 
				GHI_SendDataToBuffer("ItemReply<"..index1.."><"..index2..">",value2,player);
			end
		end
		
		GHI_SendDataToBuffer("ItemReplyEnd",index1,player);				
		
		
	else
		
	end
	
end

function GHI_RecieveItemDataVersion(data,sender)  -- GHR_Message("As: Recieved data version");
	local ID,version = strsplit(":",data);
	if not(ID) or not(version) then return end
	if not(type(GHI_ItemData[ID]) == "table") then return end
	
	local ownVersion = GHI_ItemData[ID].version;
	if not(ownVersion) then
		ownVersion = 0;
	end
	version = tonumber(version);
	ownVersion = tonumber(ownVersion);
	if not(version) or not(ownVersion) then
		return;
	end
	
	if ownVersion > version then
		GHI_SendItemData(ID,sender)  --GHR_Message("A1: Sending data.");
	end
	--GHI_Message(ownVersion.." == "..version);
	--GHR_Message("Ae: End recieved data version");
end


function GHI_SendPing(player)
	GHI_SendData("AddonVersionReq",nil,player);
	GHI_PingedPlayer = player;
end

function GHI_RecievePing(player,data)
	
	GHI_Message("Ping reply from "..player);
	GHI_Message("Version "..data);
	GHI_PingedPlayer = nil;
end



--	======================== Bandwith analyzing ========================
function GHI_MainMenuBarPerformanceBarFrame_OnEnter(f)
	orig_MainMenuBarPerformanceBarFrame_OnEnter(f);
	
	local Max = ChatThrottleLib.BURST
	local avail = ChatThrottleLib:UpdateAvail();
	if ChatThrottleLib.bChoking == true then
		Max = ChatThrottleLib.MAX_CPS;
	end
	
	local qSize = 0;
	for _,Prio in pairs(ChatThrottleLib.Prio) do
		for _,pipe in pairs(Prio.ByName) do
			qSize = qSize + #pipe;
		end
	end
	
	GameTooltip:AddLine("\nBandwidth Used");
	GameTooltip:AddLine(format("%.0f / %.0f b/sec (%.0f%%).",
		Max-avail,
		Max,
		((Max-avail)/Max)*100
	), 1.0, 1.0, 1.0);
	GameTooltip:AddLine(format("%.0f messages in queue.",
		qSize
	), 1.0, 1.0, 1.0);
	if ChatThrottleLib.bChoking then
		GameTooltip:AddLine("Bandwidth lowered due to zoning or low framerate.");
	end
	GameTooltip:Show();
end

PERFORMANCEBAR_UPDATE_INTERVAL = 1;

