--[[
##############################################################################
S V U I   By: Munglunch
##############################################################################

##########################################################
LOCALIZED LUA FUNCTIONS
##########################################################
]]--
--[[ GLOBALS ]]--
local _G = _G;
local unpack 	= _G.unpack;
local select 	= _G.select;
local pairs 	= _G.pairs;
local ipairs 	= _G.ipairs;
local type 		= _G.type;
local error 	= _G.error;
local pcall 	= _G.pcall;
local assert 	= _G.assert;
local tostring 	= _G.tostring;
local tonumber 	= _G.tonumber;
local tinsert 	= _G.tinsert;
local string 	= _G.string;
local math 		= _G.math;
local table 	= _G.table;
--[[ STRING METHODS ]]--
local lower, upper = string.lower, string.upper;
local find, format, len, split = string.find, string.format, string.len, string.split;
local match, sub, join = string.match, string.sub, string.join;
local gmatch, gsub = string.gmatch, string.gsub;
--[[ MATH METHODS ]]--
local abs, ceil, floor, round = math.abs, math.ceil, math.floor, math.round;  -- Basic
--[[ TABLE METHODS ]]--
local wipe, sort = table.wipe, table.sort;
--[[
##########################################################
GET ADDON DATA
##########################################################
]]--
local SV = select(2, ...)
local L = SV.L
local Reports = SV.Reports;
--[[
##########################################################
FRIENDS STATS
##########################################################
]]--
local HEX_COLOR = "22FFFF";
local TEXT_PATTERN1 = "%s: |cff%s%d|r";
local TEXT_PATTERN2 = "|cff%02x%02x%02x%s|r |cff%02x%02x%02x%d|r";
local TEXT_PATTERN3 = "%s |cff%02x%02x%02x%d|r %s%s";
local TEXT_PATTERN4 = FRIENDS_LIST_ONLINE .. ": %s/%s";
local friendOnline, friendOffline = gsub(ERR_FRIEND_ONLINE_SS, "\124Hplayer:%%s\124h%[%%s%]\124h", ""), gsub(ERR_FRIEND_OFFLINE_S, "%%s", "");
local FRIENDS_LIST_DIRTY = false;
local FRIENDSLIST = {};

SV.SystemAlert.SET_BN_BROADCAST={
	text = BN_BROADCAST_TOOLTIP,
	button1 = ACCEPT,
	button2 = CANCEL,
	hasEditBox = 1,
	editBoxWidth = 350,
	maxLetters = 127,
	OnAccept = function(self) BNSetCustomMessage(self.editBox:GetText()) end,
	OnShow = function(self) self.editBox:SetText(select(4, BNGetInfo()) ) self.editBox:SetFocus() end,
	OnHide = ChatEdit_FocusActiveWindow,
	EditBoxOnEnterPressed = function(self) BNSetCustomMessage(self:GetText()) self:GetParent():Hide() end,
	EditBoxOnEscapePressed = function(self) self:GetParent():Hide() end,
	timeout = 0,
	exclusive = 1,
	whileDead = 1,
	hideOnEscape = 1,
	preferredIndex = 3
};

local menuFrame = CreateFrame("Frame", "FriendDatatextRightClickMenu", SV.Screen, "UIDropDownMenuTemplate")
local menuList = {
	{ text = OPTIONS_MENU, isTitle = true,notCheckable=true},
	{ text = INVITE, hasArrow = true,notCheckable=true, },
	{ text = CHAT_MSG_WHISPER_INFORM, hasArrow = true,notCheckable=true, },
	{ text = PLAYER_STATUS, hasArrow = true, notCheckable=true,
		menuList = {
			{ text = "|cff2BC226"..AVAILABLE.."|r", notCheckable=true, func = function() if IsChatAFK() then SendChatMessage("", "AFK") elseif IsChatDND() then SendChatMessage("", "DND") end end },
			{ text = "|cffE7E716"..DND.."|r", notCheckable=true, func = function() if not IsChatDND() then SendChatMessage("", "DND") end end },
			{ text = "|cffFF0000"..AFK.."|r", notCheckable=true, func = function() if not IsChatAFK() then SendChatMessage("", "AFK") end end },
		},
	},
	{ text = BN_BROADCAST_TOOLTIP, notCheckable=true, func = function() SV:StaticPopup_Show("SET_BN_BROADCAST") end },
}

local function inviteClick(self, name)
	menuFrame:Hide()

	if type(name) ~= 'number' then
		InviteUnit(name)
	else
		BNInviteFriend(name);
	end
end

local function whisperClick(self, name, battleNet)
	menuFrame:Hide()

	if battleNet then
		ChatFrame_SendSmartTell(name)
	else
		SetItemRef( "player:"..name, ("|Hplayer:%1$s|h[%1$s]|h"):format(name), "LeftButton" )
	end
end

local REPORT_NAME = "Friends";

local Report = Reports:NewReport(REPORT_NAME, {
	type = "data source",
	text = REPORT_NAME .. " Info",
	icon = [[Interface\Addons\SVUI_!Core\assets\icons\SVUI]]
});

Report.events = {
	"PLAYER_ENTERING_WORLD",
	"BN_FRIEND_ACCOUNT_ONLINE",
	"BN_FRIEND_ACCOUNT_OFFLINE",
	"BN_FRIEND_INFO_CHANGED",
	"BN_FRIEND_TOON_ONLINE",
	"BN_FRIEND_TOON_OFFLINE",
	"BN_TOON_NAME_UPDATED",
	"FRIENDLIST_UPDATE",
	"CHAT_MSG_SYSTEM"
};

Report.OnEvent = function(self, event, ...)
	local _, onlineFriends = GetNumFriends()
	local _, numBNetOnline = BNGetNumFriends()
	if event == "CHAT_MSG_SYSTEM" then
		local message = select(1, ...)
		if not (find(message, friendOnline) or find(message, friendOffline)) then return end
	end
	FRIENDS_LIST_DIRTY = false
	local amt = onlineFriends + numBNetOnline
	self.text:SetFormattedText(TEXT_PATTERN1, L['Friends'], HEX_COLOR, amt)
end

Report.OnClick = function(self, button)
	Reports.ToolTip:Hide()

	if button == "RightButton" then
		local menuCountWhispers = 0
		local menuCountInvites = 0
		local classc, levelc, friend

		menuList[2].menuList = {}
		menuList[3].menuList = {}

		local currentFaction = UnitFactionGroup("player");
		local friendsTable = FRIENDSLIST['General'];
		if #friendsTable > 0 then
			for i = 1, #friendsTable do
				friend = friendsTable[i]
				if (friend.ONLINE) then
					menuCountInvites = menuCountInvites + 1
					menuCountWhispers = menuCountWhispers + 1

					classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)
					classc = classc or levelc;

					menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,classc.r*255,classc.g*255,classc.b*255,friend.NAME,levelc.r*255,levelc.g*255,levelc.b*255,friend.LVL), arg1 = friend.NAME,notCheckable=true, func = inviteClick}
					menuList[3].menuList[menuCountWhispers] = {text = format(TEXT_PATTERN2,levelc.r*255,classc.r*255,classc.g*255,classc.b*255,friend.NAME,levelc.g*255,levelc.b*255,friend.LVL), arg1 = friend.NAME,notCheckable=true, func = whisperClick}
				end
			end
		end

		for client, list in pairs(FRIENDSLIST) do
			if((client ~= 'General') and (#list > 0)) then
				for i = 1, #list do
					friend = list[i]
					if (friend.ONLINE) then
						local realID = friend.BNET_NAME
						menuCountWhispers = menuCountWhispers + 1
						menuList[3].menuList[menuCountWhispers] = {text = realID, arg1 = realID, arg2 = true, notCheckable=true, func = whisperClick}

						if((BNET_CLIENT_WOW == friend.CLIENT) and (currentFaction == friend.FACTION)) then
							classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)
							classc = classc or levelc
							menuCountInvites = menuCountInvites + 1

							menuList[2].menuList[menuCountInvites] = {text = format(TEXT_PATTERN2,classc.r*255,classc.g*255,classc.b*255,friend.NAME,levelc.r*255,levelc.g*255,levelc.b*255,friend.LVL), arg1 = friend.CLIENT, notCheckable=true, func = inviteClick}
						end
					end
				end
			end
		end

		EasyMenu(menuList, menuFrame, "cursor", 0, 0, "MENU", 2)
	else
		ToggleFriendsFrame()
	end
end

Report.OnEnter = function(self)
	Reports:SetDataTip(self)
	local groupString = "";
	local numberOfFriends, onlineFriends = GetNumFriends()
	local totalBNet, numBNetOnline = BNGetNumFriends()
	local totalonline = onlineFriends + numBNetOnline

	-- no friends online, quick exit
	if totalonline == 0 then return end

	if(not FRIENDS_LIST_DIRTY) then
		FRIENDSLIST = SV:GetFriendsCache(numberOfFriends, totalBNet);
		FRIENDS_LIST_DIRTY = true
	end

	local totalfriends = numberOfFriends + totalBNet
	local zonec, classc, levelc, realmc, friend
	Reports.ToolTip:AddDoubleLine(L['Friends List'], format(TEXT_PATTERN4, totalonline, totalfriends), 0.4,0.78,1, 0.4,0.78,1)
	Reports.ToolTip:AddLine(' ')

	local currentZone = GetRealZoneText();
	local currentRealm = GetRealmName();

	if onlineFriends > 0 then
		local friendsTable = FRIENDSLIST['General'];
		local friendsFound = false;
		for i = 1, #friendsTable do
			friend = friendsTable[i]
			--print(table.tostring(friend))
			if friend.ONLINE then
				if(currentZone == friend.LOC) then
					zonec = SV.media.color.green
				else
					zonec = SV.media.color.medium
				end
				classc, levelc = RAID_CLASS_COLORS[friend.CLASS], GetQuestDifficultyColor(friend.LVL)

				classc = classc or GetQuestDifficultyColor(friend.LVL)

				if UnitInParty(friend.NAME) or UnitInRaid(friend.NAME) then
					groupString = "|cffaaaaaa*|r";
				else
					groupString = "";
				end
				Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN3, friend.NAME, levelc.r*255, levelc.g*255, levelc.b*255, friend.LVL, groupString, friend.STATUS ), friend.LOC, classc.r, classc.g, classc.b, zonec.r, zonec.g, zonec.b)
				friendsFound = true;
			end
		end
		if(friendsFound) then
			Reports.ToolTip:AddLine(' ')
		end
	end

	if numBNetOnline > 0 then
		--Reports.ToolTip:AddLine(BATTLENET_OPTIONS_LABEL)
		local status = 0
		for client, list in pairs(FRIENDSLIST) do
			if((client ~= 'General') and (#list > 0)) then
				local GROUP_HEADER = BNet_GetClientEmbeddedTexture(client, 16, 16, 0, -1)..client;
				Reports.ToolTip:AddLine(GROUP_HEADER)
				--Reports.ToolTip:AddLine(' ')
				for i = 1, #list do
					friend = list[i]
					--print(table.tostring(friend))
					if friend.ONLINE then
						if friend.CLIENT == BNET_CLIENT_WOW then
							classc = RAID_CLASS_COLORS[friend.CLASS] or RAID_CLASS_COLORS["PRIEST"]

							if UnitInParty(friend.NAME) or UnitInRaid(friend.NAME) then
								groupString = "|cffaaaaaa*|r";
							else
								groupString = "";
							end

							if friend.LVL ~= '' then
								levelc = GetQuestDifficultyColor(friend.LVL)
								Reports.ToolTip:AddDoubleLine(format(TEXT_PATTERN2, classc.r*255, classc.g*255, classc.b*255, friend.NAME, levelc.r*255, levelc.g*255, levelc.b*255, friend.LVL, groupString, 255, 0, 0, friend.STATUS), friend.BNET_NAME, 238, 238, 238, 0.51, 0.773, 1)
							else
								Reports.ToolTip:AddDoubleLine(format("|cff%02x%02x%02x%s|r", classc.r*255, classc.g*255, classc.b*255, friend.NAME, groupString, 255, 0, 0, friend.STATUS), friend.BNET_NAME, 238, 238, 238, 0.51, 0.773, 1)
							end

							if IsShiftKeyDown() then
								if(currentZone == friend.LOC) then zonec = SV.media.color.green else zonec = SV.media.color.medium end
								if(currentRealm == friend.REALM) then realmc = SV.media.color.green else realmc = SV.media.color.medium end
								Reports.ToolTip:AddDoubleLine(friend.LOC, friend.REALM, zonec.r, zonec.g, zonec.b, realmc.r, realmc.g, realmc.b)
							end
						else
							Reports.ToolTip:AddLine(friend.BNET_NAME, 0.51, 0.773, 1)
						end
					end
				end
			end
		end
	end

	Reports:ShowDataTip()
end

Report.OnInit = function(self)
	local numberOfFriends, onlineFriends = GetNumFriends()
	local totalBNet, numBNetOnline = BNGetNumFriends()
	FRIENDSLIST = SV:GetFriendsCache(numberOfFriends, totalBNet);
end
