

local comm = GHI_Comm();

local Buff;

function GHI_BuffHookings(self)
	
	Buff = GHU_New("buff");
	self:RegisterEvent("PLAYER_AURAS_CHANGED");
	self:RegisterEvent("PLAYER_TARGET_CHANGED");
	Buff:SetFeedbackFunc(GHI_BuffChanged)
	return
	
	
end

GHI_DelayCastData = {};
-- Player in function 
function ApplyGHIBuff(name,text,texture,untilCancelled,filter,debuffType,duration,cancelable,stackable,count,delay)
	if type(delay)=="number" and delay > 0 then
		local r = 1;
		while GHI_DelayCastData[r] do
			r=r+1;
		end
		GHI_DelayCastData[r] = {name,text,texture,untilCancelled,filter,debuffType,duration,cancelable,stackable,count,0};
		
		GHI_DoScript("ApplyGHIBuff(unpack(GHI_DelayCastData["..r.."])); GHI_DelayCastData["..r.."] = nil;",delay);
		return;
	end

	
	Buff:CastBuff(string.lower(filter),name,UnitGUID("player"),name,text,texture,(not(untilCancelled) and duration)or 0 ,(not(untilCancelled) and GetTime() + duration) or 0,count	,debuffType,stackable)

end

function ReceiveApplyBuff(sender,click)
	ApplyGHIBuff(click.buffName,click.buffDetails,click.buffIcon,click.untillCanceled,click.filter,click.buffType,click.buffDuration,click.cancelable,click.stackable,click.count or 1,click.delay or 0)
end
comm.AddRecieveFunc("ApplyBuff",ReceiveApplyBuff)

function CountGHIBuff(name,unit)
	unit = unit or "player";
	return Buff:CountBuff(name,UnitGUID(unit))
end

function RemoveGHIBuff(name,count) -- now only called by scripts
--name = "\""..name.."\"";
--print(name);
	assert(type(name)=="string" and type(count)=="number","RemoveGHIBuff useage: name (string), count (number).")
	
	Buff:RemoveBuff(name,UnitGUID("player"),count)
end

function RemoveAllGHIBuffs()
	Buff:ClearAllBuffs(UnitGUID("player"));
	GHI_DelayCastData = {};
end

-- Target etc in
GHI_SubscribedPlayers = {};

local subscriptionsSend = {};
GHI_OldBuffPlayers = {};
GHI_OldBuffReqs = {};

function GHI_CheckTarget() 
	local name, realm = UnitName("target")
	if UnitIsPlayer("target") and UnitFactionGroup("target") == UnitFactionGroup("player") and not(UnitName("player")==name) and realm == nil then
		if type(subscriptionsSend[name])=="number" and (GetTime() - subscriptionsSend[name]) < 60*3 then
			return;
		end
		comm.Send("NORMAL",name,"BuffSubscribe",60*5)
		subscriptionsSend[name] = GetTime();
	end
end

function GHI_BuffRecieveSubscription(sender,subscriptionTime,...)
	GHI_SubscribedPlayers[sender] = GetTime() + subscriptionTime;
	GHI_SendBuffInfo(sender);
end
comm.AddRecieveFunc("BuffSubscribe",GHI_BuffRecieveSubscription)

function GHI_SendBuffInfo(players) 
	local guid = UnitGUID("player");
	local buffs,debuffs = Buff:Serialize(guid);
	
	if type(players) == "string" then
		local name = players;
		players = {};
		players[name] = "dummy";
	end
	
	
	for name,_ in pairs(players) do
		comm.Send("NORMAL",name,"BuffInfo",guid,buffs,debuffs)
	end
end

function GHI_BuffRecieveInfo(sender,guid,buffData,debuffData,...)
	Buff:Deserialize(guid,buffData,debuffData);
end
comm.AddRecieveFunc("BuffInfo",GHI_BuffRecieveInfo)

function GHI_BuffChanged(guid)
	if UnitGUID("player")==guid then
		GHI_OldBuffPlayers["own time"] = GetTime();
		GHI_UpdateBuffSubscriptions()
		GHI_SendBuffInfo(GHI_SubscribedPlayers)
		
		
	end
end


function GHI_UpdateBuffSubscriptions()
	for player,timeout in pairs(GHI_SubscribedPlayers) do
		if timeout < GetTime() then
			GHI_SubscribedPlayers[player] = nil;
		end
	end
end


function Buffformat()
	return Buff:Serialize(UnitGUID("player"));
end
