--[[
HoloFriends addon created by Holo, continued by Zappster, followed by Andymon

Get the latest version at wow.curse.com

See HoloFriends_change.log for more informations  
]]

--[[

This file defines the hooks used

]]


-- switches to prevent output of some system messages to the chat
HoloFriends_ignoreAddFriendsSysMsg = false;
HoloFriends_ignoreRemoveFriendsSysMsg = false;

-- switch to trigger HoloFriends_List_Update
HoloFriends_RunListUpdate = "";

-- strings computed from global strings
local HF_ERR_FRIEND_ADDED_S = "";
local HF_ERR_FRIEND_ALREADY_S = "";
local HF_ERR_FRIEND_REMOVED_S = "";
local HF_WHO_LIST_FORMAT = "";
local HF_WHO_LIST_GUILD_FORMAT = "";
HoloFriends_WHO_NUM_RESULTS = "";

-- saved text from autocomplete
local HF_AutoComplete_OldText = "";

-- saved hook
local HFF_FriendsFrame_OnEvent_Orig = nil;


-- Initialisation of the hooks
function HoloFriendsHooks_OnLoad()
	hooksecurefunc("UnitPopup_OnClick",   HoloFriends_UnitPopup_OnClick);
	hooksecurefunc("UnitPopup_OnUpdate",  HoloFriends_UnitPopup_OnUpdate);
	hooksecurefunc("AutoComplete_Update", HoloFriends_AutoComplete_Update);

	-- Add a Message Event Filter (replaces old hook methode)
	ChatFrame_AddMessageEventFilter("CHAT_MSG_SYSTEM", HoloFriends_ChatFrame_MessageEventFilter);

	-- hook FriendsFrame_OnEvent to prevent who-frame popup
	HFF_FriendsFrame_OnEvent_Orig = FriendsFrame_OnEvent;
	FriendsFrame_OnEvent = HoloFriends_FriendsFrame_OnEvent;

	-- setup of some strings
	HF_ERR_FRIEND_ADDED_S   = string.gsub(ERR_FRIEND_ADDED_S,   "%%s", "%.%+");
	HF_ERR_FRIEND_ALREADY_S = string.gsub(ERR_FRIEND_ALREADY_S, "%%s", "%.%+");
	HF_ERR_FRIEND_REMOVED_S = string.gsub(ERR_FRIEND_REMOVED_S, "%%s", "%.%+");

	HF_WHO_LIST_FORMAT = string.gsub(WHO_LIST_FORMAT, "%%%d*%$?s", "%.%*");
	HF_WHO_LIST_FORMAT = string.gsub(HF_WHO_LIST_FORMAT, "%%%d*%$?d", "%%d%+");
	HF_WHO_LIST_FORMAT = string.gsub(HF_WHO_LIST_FORMAT, "%[", "%%%[");
	HF_WHO_LIST_FORMAT = string.gsub(HF_WHO_LIST_FORMAT, "%]", "%%%]");
	HF_WHO_LIST_FORMAT = string.gsub(HF_WHO_LIST_FORMAT, "%-", "%%%-");
	HF_WHO_LIST_GUILD_FORMAT = string.gsub(WHO_LIST_GUILD_FORMAT, "%%%d*%$?s", "%.%*");
	HF_WHO_LIST_GUILD_FORMAT = string.gsub(HF_WHO_LIST_GUILD_FORMAT, "%%%d*%$?d", "%%d%+");
	HF_WHO_LIST_GUILD_FORMAT = string.gsub(HF_WHO_LIST_GUILD_FORMAT, "%[", "%%%[");
	HF_WHO_LIST_GUILD_FORMAT = string.gsub(HF_WHO_LIST_GUILD_FORMAT, "%]", "%%%]");
	HF_WHO_LIST_GUILD_FORMAT = string.gsub(HF_WHO_LIST_GUILD_FORMAT, "%-", "%%%-");
	HoloFriends_WHO_NUM_RESULTS = string.gsub(WHO_NUM_RESULTS, "%%%d*%$?d", "%%d%+");
end


-- Autocompletion, mainly for send mail
local function HFF_AutoComplete_Update(self, text, cursorpos, maxarg, ...)
	local arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9 = ...;
	local numarg = select("#", ...);

	local numFriends, name;
	local list = nil;

	-- split text at cursor position
	local textlen = string.len(text);
	local subtxt1;
	if ( cursorpos > 0 ) then subtxt1 = string.sub(text, 1, cursorpos); end
	local subtxt2;
	if ( cursorpos < textlen ) then subtxt2 = string.sub(text, cursorpos + 1); end

	-- check local HoloFriends list
	list = HoloFriends_GetList();
	numFriends = table.getn(list);
	if ( (numFriends > 0) and (numarg < maxarg) ) then
		for index = 1, numFriends do
			name = HoloFriendsLists_GetName(list, index);
			if ( name == "" ) then name = nil; end
			if ( HoloFriendsFuncs_IsGroup(list, index) ) then name = nil; end
			if ( HoloFriendsLists_GetNotify(list, index) ) then name = nil; end
			if ( subtxt1 ) then
				-- subtxt1 has to start at first position in name
				if ( name and (strfind(strupper(name), strupper(subtxt1), 1, 1) == 1) ) then
					-- subtxt2 has to exist in name after the cursor position
					if ( subtxt2 and not strfind(strupper(name), strupper(subtxt2), cursorpos + 1, 1) ) then
						name = nil;
					end
				else
					name = nil;
				end
			else
				-- without subtxt1, only subtxt2 has to exist in name
				if ( name and not strfind(strupper(name), strupper(subtxt2), 1, 1) ) then
					name = nil;
				end
			end
			-- put valid name in next free argument upto maxarg is filled
			if ( name and (numarg < maxarg) ) then
				numarg = numarg + 1;
				if ( numarg == 1 ) then arg1 = name; end
				if ( numarg == 2 ) then arg2 = name; end
				if ( numarg == 3 ) then arg3 = name; end
				if ( numarg == 4 ) then arg4 = name; end
				if ( numarg == 5 ) then arg5 = name; end
				if ( numarg == 6 ) then arg6 = name; end
				if ( numarg == 7 ) then arg7 = name; end
				if ( numarg == 8 ) then arg8 = name; end
				if ( numarg == 9 ) then arg9 = name; end				
			end
		end
	end

	-- check FactionList for own chars
	local player = UnitName("player");
	local faction = UnitFactionGroup("player");
	list = HoloFriendsFuncs_RealmGetAllFactionChars();
	numFriends = table.getn(list);
	if ( (numFriends > 0) and (numarg < maxarg) ) then
		for index = 1, numFriends do
			name = list[index];
			if ( name == "" ) then name = nil; end
			if ( (name == player) or (name == faction) ) then name = nil; end
			if ( subtxt1 ) then
				-- subtxt1 has to start at first position in name
				if ( name and (strfind(strupper(name), strupper(subtxt1), 1, 1) == 1) ) then
					-- subtxt2 has to exist in name after the cursor position
					if ( subtxt2 and not strfind(strupper(name), strupper(subtxt2), cursorpos + 1, 1) ) then
						name = nil;
					end
				else
					name = nil;
				end
			else
				-- without subtxt1, only subtxt2 has to exist in name
				if (name and not strfind(strupper(name), strupper(subtxt2), 1, 1) ) then
					name = nil;
				end
			end
			-- put valid name in next free argument upto maxarg is filled
			if ( name and (numarg < maxarg) ) then
				numarg = numarg + 1;
				if ( numarg == 1 ) then arg1 = name; end
				if ( numarg == 2 ) then arg2 = name; end
				if ( numarg == 3 ) then arg3 = name; end
				if ( numarg == 4 ) then arg4 = name; end
				if ( numarg == 5 ) then arg5 = name; end
				if ( numarg == 6 ) then arg6 = name; end
				if ( numarg == 7 ) then arg7 = name; end
				if ( numarg == 8 ) then arg8 = name; end
				if ( numarg == 9 ) then arg9 = name; end				
			end
		end
	end

	if ( numarg == 1 ) then
		-- complete the name in the text field if only one left
		if ( strupper(HF_AutoComplete_OldText) ~= strupper(text) ) then
			self:SetText(arg1);
			self:SetCursorPosition(cursorpos);
			self:HighlightText(cursorpos, -1);
		end
		HF_AutoComplete_OldText = text;
		return arg1;
	end
	HF_AutoComplete_OldText = text;

	if ( numarg == 2 ) then return arg1, arg2; end
	if ( numarg == 3 ) then return arg1, arg2, arg3; end
	if ( numarg == 4 ) then return arg1, arg2, arg3, arg4; end
	if ( numarg == 5 ) then return arg1, arg2, arg3, arg4, arg5; end
	if ( numarg == 6 ) then return arg1, arg2, arg3, arg4, arg5, arg6; end
	if ( numarg == 7 ) then return arg1, arg2, arg3, arg4, arg5, arg6, arg7; end
	if ( numarg == 8 ) then return arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8; end
	if ( numarg == 9 ) then return arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9; end
end


function HoloFriends_AutoComplete_Update(parent, text, cursorPosition)
	if ( not parent.autoCompleteParams ) then 
		return;
	end
	if ( not text or (text == "") ) then
		return;
	end
	if ( not cursorPosition or (cursorPosition > strlen(text)) ) then
		return;
	end
	local include = parent.autoCompleteParams.include;
	if ( (include ~= AUTOCOMPLETE_FLAG_ALL) and (include ~= AUTOCOMPLETE_FLAG_FRIEND) ) then
		return;
	end
	local exclude = parent.autoCompleteParams.exclude;
	if ( (exclude == AUTOCOMPLETE_FLAG_ALL) or (exclude == AUTOCOMPLETE_FLAG_FRIEND) ) then
		return;
	end
	local maxarg = AUTOCOMPLETE_MAX_BUTTONS + 1;
	local numarg = select("#", GetAutoCompleteResults(text,	include, exclude, maxarg, cursorPosition));
	if ( (numarg <= 9) and (numarg < maxarg) ) then
		AutoComplete_UpdateResults(AutoCompleteBox,
			HFF_AutoComplete_Update(parent, text, cursorPosition, AUTOCOMPLETE_MAX_BUTTONS+1,
				GetAutoCompleteResults(text, include, exclude, maxarg, cursorPosition)));
	end
end


-- Process drop down menu click
function HoloFriends_UnitPopup_OnClick(self)
	local button = self.value;
	local dropdownFrame = UIDROPDOWNMENU_INIT_MENU;
	local name   = dropdownFrame.name;
	local id     = dropdownFrame.userData;

	if ( button == "HOLOFRIENDS_ADDCOMMENT" ) then
		if ( dropdownFrame == HoloFriendsDropDown ) then
			local list = HoloFriends_GetList();
			local index = HoloFriends_GetLastClickedIndex();
			list[index].remove = nil;
			StaticPopup_Show("HOLOFRIENDS_ADDCOMMENT", name);
		elseif ( dropdownFrame == HoloIgnoreDropDown ) then
			StaticPopup_Show("HOLOIGNORE_ADDCOMMENT", name);
		end
	elseif ( button == "HOLOFRIENDS_ADDGROUP" ) then
		StaticPopup_Show("HOLOFRIENDS_ADDGROUP");
	elseif ( button == "HOLOFRIENDS_REMOVEGROUP" ) then
		if ( dropdownFrame == HoloFriendsDropDown ) then
			HoloFriendsFuncs_RemoveGroup(HoloFriends_GetList(), id, FRIENDS);
			HoloFriends_DeselectEntry();
			HoloFriends_List_Update();
			if ( HoloFriends_ShareFrame:IsShown() ) then
				HoloFriendsShare_OnShow();
			end
		elseif ( dropdownFrame == HoloIgnoreDropDown ) then
			HoloFriendsFuncs_RemoveGroup(HoloIgnore_GetList(), id, IGNORE);
			HoloIgnore_DeselectEntry();
			HoloIgnore_List_Update();
		end
	elseif ( button == "HOLOFRIENDS_ADDFRIEND" ) then
		HoloFriends_AddFriend(name);
	elseif ( button == "HOLOFRIENDS_ADDIGNORE" ) then
		HoloIgnore_AddIgnore(name);
	elseif ( button == "HOLOFRIENDS_WHOREQUEST" ) then
		SendWho("n-"..name);
	elseif ( button == "HOLOFRIENDS_RENAMEGROUP" ) then
		if ( dropdownFrame == HoloFriendsDropDown ) then
			StaticPopup_Show("HOLOFRIENDS_RENAMEGROUP");
		elseif ( dropdownFrame == HoloIgnoreDropDown ) then
			StaticPopup_Show("HOLOIGNORE_RENAMEGROUP");
		end
	end

	HoloFriends_DropDownBG_Hide();
end


-- Disable buttons in opend drop down menu
function HoloFriends_UnitPopup_OnUpdate(elapsed)
	if ( not DropDownList1:IsShown() ) then
		return;
	end

	-- If none of the untipopup frames are visible then return
	for index, value in pairs(UnitPopupFrames) do
		if ( UIDROPDOWNMENU_OPEN_MENU:GetName() == value ) then
			break;
		elseif ( index == #UnitPopupFrames ) then
			return;
		end
	end

	local dropdown = UIDROPDOWNMENU_OPEN_MENU;
	local which = dropdown.which;
	local name = dropdown.name;
	if ( not name ) then
		name = UnitName(dropdown.unit);
	end

	if ( (which == "PARTY") or (which == "PLAYER") or (which == "RAID") or (which == "FRIEND") ) then
		local nameinignore = HoloFriendsFuncs_ContainsPlayer(HoloIgnore_GetList(),name);
		local nameinfriends = HoloFriendsFuncs_ContainsPlayer(HoloFriends_GetList(), name);
		local count = 0;
		for index, value in ipairs(UnitPopupMenus[which]) do
			if ( UnitPopupShown[UIDROPDOWNMENU_MENU_LEVEL][index] == 1 ) then
				count = count + 1;
				-- disable add player to list if it exist already at one of the lists
				if ( nameinignore or nameinfriends ) then
					if ( (value == "HOLOFRIENDS_ADDIGNORE") or
					     (value == "HOLOFRIENDS_ADDFRIEND") )
					then
						UIDropDownMenu_DisableButton(1, count + 1);
					end
				end
				-- disable the protected function set focus for this tainted menu (gives en error)
				if ( value == "SET_FOCUS" and HoloFriends_MenuModDone ) then
					UIDropDownMenu_DisableButton(1, count + 1);
				end
				if ( value == "IGNORE" ) then
					UIDropDownMenu_DisableButton(1, count + 1);
				end
			end
		end
	end
end


-- Event filter for CHAT_MSG_SYSTEM messages
function HoloFriends_ChatFrame_MessageEventFilter(self, event, msg)
	local skipmsg = false;

	if ( string.match(msg, HF_ERR_FRIEND_ADDED_S) ) then
		if ( not HoloFriends_SetNotifyOff ) then
			HoloFriends_FriendListMSGEvent = true;
		end
		if ( HoloFriends_ignoreAddFriendsSysMsg ) then
			HoloFriends_ignoreAddFriendsSysMsg = false;
			skipmsg = true;
		end
	end

	if ( string.match(msg, HF_ERR_FRIEND_REMOVED_S) ) then
		if ( not HoloFriends_SetNotifyOn ) then
			HoloFriends_FriendListMSGEvent = true;
		end
		if ( HoloFriends_ignoreRemoveFriendsSysMsg ) then
			HoloFriends_ignoreRemoveFriendsSysMsg = false;
			skipmsg = true;
		end
	end

	if ( string.match(msg, HF_ERR_FRIEND_ALREADY_S) ) then HoloFriends_FriendListMSGEvent = true; end
	if ( string.match(msg, ERR_FRIEND_LIST_FULL) ) then HoloFriends_FriendListMSGEvent = true; end
	if ( string.match(msg, ERR_FRIEND_NOT_FOUND) ) then HoloFriends_FriendListMSGEvent = true; end
	if ( string.match(msg, ERR_FRIEND_SELF) ) then HoloFriends_FriendListMSGEvent = true; end
	if ( string.match(msg, ERR_FRIEND_WRONG_FACTION) ) then HoloFriends_FriendListMSGEvent = true; end

	if ( not HoloFriends_RunListUpdate or (HoloFriends_RunListUpdate == "") ) then
		HoloFriends_FriendListMSGEvent = false;
	end

	if ( HoloFriends_FriendListMSGEvent and HoloFriends_FriendListUPDATEEvent ) then
		HoloFriends_SetNotifyOn = false;
		HoloFriends_SetNotifyOff = false;
		HoloFriends_FriendListMSGEvent = false;
		HoloFriends_FriendListUPDATEEvent = false;
		if ( HoloFriends_RunListUpdate == "RunUpdate" ) then
			HoloFriends_RunListUpdate = "";
			HoloFriends_List_Update();
		end
		if ( (difftime(time(), HoloFriends_ListUpdateStartTime) > HoloFriends_ListUpdateMaxSec) ) then
			HoloFriends_RunListUpdate = "";
		end
		if ( HoloFriends_RunListUpdate == "RunLocal" ) then
			HoloFriends_RunListUpdate = "";
			HoloFriends_CheckLocalList();
		end
		if ( HoloFriends_RunListUpdate == "RunServer" ) then
			HoloFriends_RunListUpdate = "";
			HoloFriends_CheckServerList();
		end
	end

	if ( skipmsg ) then
		return true;
	end

	if ( GetTime() < (HoloFriends_interceptWhoResults + HoloFriends_whoCheckInterval) ) then
		local debug_output = 1;
		if ( string.match(msg, HF_WHO_LIST_FORMAT) ) then
			HoloFriends_chat("Intercepted who result: "..msg, debug_output);
			return true;
		elseif ( string.match(msg, HF_WHO_LIST_GUILD_FORMAT) ) then
			HoloFriends_chat("Intercepted who result: "..msg, debug_output);
			return true;
		elseif ( string.match(msg, HoloFriends_WHO_NUM_RESULTS) ) then
			HoloFriends_chat("Intercepted who total: "..msg, debug_output);
			local numWho = GetNumWhoResults();
			if ( numWho == 0 ) then
				local list = HoloFriends_GetList();
				playerIndex = HoloFriendsFuncs_ContainsPlayer(list, HoloFriends_queryingThisGuy);
				if ( playerIndex ) then
					list[playerIndex].connected = false;
				end
			end
			HoloFriends_interceptWhoResults = 0;
			return true;
		end
	else
		HoloFriends_interceptWhoResults = 0;
	end
end


-- Prevent popup of who-window during scan in case of many who-results
function HoloFriends_FriendsFrame_OnEvent(self, event, ...)
	if ( (event == "WHO_LIST_UPDATE") and 
	     (GetTime() < (HoloFriends_interceptWhoResults + HoloFriends_whoCheckInterval)) )
	then
		HoloFriendsScan_CheckWhoListResult(HoloFriends_GetList());
	else
		HFF_FriendsFrame_OnEvent_Orig(self, event, ...);
	end
end
