--[[
FuBar_EmoteFu2

Hello!
This is a continuation (FuBar2 port) of the brilliant EmoteFu addon by Cilraaz.
I've taken the liberty of adding features such as real custom emotes,
a detachable favorites tablet (FuBar <3), alphabetical sorting etc.

Hope this is of use to you roleplayers out there (or just anyone who wants to
save a bit of bar space)!

AKX
(Zerun @ Moonglade-EU)

-- Original description follows. --

EmoteFu
by Cilraaz of Cenarion Circle

Please note that this mod is a port of TitanEmoteMenu by Dsanai of Whisperwind.
Some of the functions are largely based on that mod.  The entire emote list is
also borrowed from TitanEmoteMenu.  So a huge thanks to Dsanai for even making 
this mod possible.

Also, a special thanks to chuckg from www.wowinterface.com.  Chuckg helped in
straightening out a few problem areas in my code, as well as pointing out the
DoEmote API function, which was invalueable.

Welcome to EmoteFu!  This is a FuBar port of TitanEmoteMenu.  It is meant to
give players an easily accessible menu of emotes.  The emotes have been sorted
by category (ie. "Friendly", "Hostile", etc) to make it quite simple to quickly
access the emote you want.  Emotes can end up in more than one category, where 
applicable (ie. /dance can be found in "Happy" and "Affection").

Emotes in the list are colorized and marked with a label (A, V, AV) if they are
Animated, Voice, or Both.

It is also possible to add your own custom emotes!  To do so, simply edit the
EmoteData.lua file.  You will want to match the format exactly or that mod may
no longer function!  If that occurs, just replace the EmoteData.lua with a good
copy from the zip.

--]]

local dewdrop = AceLibrary("Dewdrop-2.0")
local tablet = AceLibrary("Tablet-2.0")
local L = AceLibrary("AceLocale-2.2"):new("FuBar_EmoteFu2")


EmoteFu = AceLibrary("AceAddon-2.0"):new("FuBarPlugin-2.0","AceDB-2.0","AceEvent-2.0")
EmoteFu.version = GetAddOnMetadata("FuBar_EmoteFu2","Version")
EmoteFu.hasIcon = "Interface\\Icons\\Spell_Shadow_Charm"
EmoteFu.hasNoText = true
EmoteFu.clickableTooltip = true
--EmoteFu.cannotDetachTooltip = true
EmoteFu:RegisterDB("EmoteFuDB")
EmoteFu:RegisterDefaults('profile', {
	favs = {},
	customs={},
	simpleTablet=nil,
	simpleMenu=nil,
	showCommand=true,
	}
)

function EmoteFu:ReplaceTextPlaceholders(info,tinfo)
	tinfo=tinfo or self.tinfo;
	if self.tinfo.hasTarget then
		info = string.gsub(info,"<Target>",self.tinfo.hasTarget);
	end
	info = string.gsub(info,"<He>",self.tinfo.genderHe);
	info = string.gsub(info,"<His>",self.tinfo.genderHis);
	info = string.gsub(info,"<he>",self.tinfo.genderhe);
	info = string.gsub(info,"<his>",self.tinfo.genderhis);	
	return info;
end

function EmoteFu:FormatEmoteText(k2,forOutput)
	local v2=EL_Emotes[k2];
	info = self:GetOnDemandText(v2,self.tinfo.hasTarget);
	info = self:ReplaceTextPlaceholders(info);
	return info;
end

local function capitalize(s)
	return string.upper(strsub(s,1,1))..strsub(s,2)
end

function EmoteFu:AddEmoteToMenu(k2,nocheck)
	local info = nil;
	local v2=EL_Emotes[k2];
	local txt;
	local hint;
	local show_cmd = self.db.profile.showCommand and not self.db.profile.simpleMenu
	if(v2) then
		info=self:FormatEmoteText(k2);

		if v2.custom then
			slshCmd = L["Custom"];
			hint = L["Shift+Click: Add/Remove Favorite, Ctrl+Click: Delete Custom"];
		else
			slshCmd = "/"..k2;
			hint = L["Shift+Click: Add/Remove Favorite"];
		end
		if self.db.profile.simpleMenu then
			txt=capitalize(k2)
		elseif show_cmd then
			txt=slshCmd.."  "..info
		else
			txt=info
		end
		dewdrop:AddLine(
			'text', txt,
			'tooltipTitle', slshCmd,
			'tooltipText', info.."\n\n|cFFFF0000"..hint.."|r",
			'arg1', k2,
			'func', function(k2) self:HandleModClick(k2) end,
			'hasArrow', (v2.custom and nocheck==nil),
			--'closeWhenClicked', true,
			'checked', (nocheck==nil and self.db.profile.favs[k2]~=nil)
		)
	end
end

function EmoteFu:GetFavs()
	local keys={};
	for k, _ in pairs(self.db.profile.favs) do
		table.insert(keys,k);
	end
	table.sort(keys);
	return keys;
end

function EmoteFu:GetCustoms()
	local keys={};
	for k, _ in pairs(self.db.profile.customs) do
		table.insert(keys,k);
	end
	table.sort(keys);
	return keys;
end

function EmoteFu:UpdateTInfo()
	self.tinfo={};
	self.tinfo.hasTarget = UnitName("target");
	self.tinfo.genderCode = UnitSex("player");

	if self.tinfo.genderCode==2 then
		self.tinfo.genderHe = L["He"];
		self.tinfo.genderhe = L["he"];
		self.tinfo.genderHis = L["His"];
		self.tinfo.genderhis = L["his"];
	else
		self.tinfo.genderHe = L["She"];
		self.tinfo.genderhe = L["she"];
		self.tinfo.genderHis = L["Her"];
		self.tinfo.genderhis = L["her"];
	end
end

function EmoteFu._toggleOpt(opt)
	if EmoteFu.db.profile[opt] then
		EmoteFu.db.profile[opt]=nil
	else
		EmoteFu.db.profile[opt]=1
	end
end

function EmoteFu:_AddMenuToggle(name,opt)
	dewdrop:AddLine('text', name, 'arg1', opt, 'func', self._toggleOpt,'checked', self.db.profile[opt])
end

function EmoteFu:OnMenuRequest(level,value,it,v1,v2,v3,v4)
	self:UpdateTInfo()

	if level == 1 then
		for _, k in ipairs(self:GetFavs()) do
			self:AddEmoteToMenu(k,1)
		end
		dewdrop:AddLine('text', L['All'], 'value', -1, 'hasArrow', true)
		dewdrop:AddLine('text', L['Alpha'], 'value', -2, 'hasArrow', true)
		dewdrop:AddLine('text', L['Animation'], 'value', -3, 'hasArrow', true)
		dewdrop:AddLine('text', L['Custom'], 'value', -4, 'hasArrow', true)
		for k, v in pairs(EL_Types) do
		    dewdrop:AddLine( 'text', v, 'value', k, 'hasArrow', true)
		end
		dewdrop:AddLine('text', L['Options'], 'value', 0, 'hasArrow', true)
	elseif level == 2 then
		if value==-2 then -- Alpha
			for i=65,90 do
				local c=string.char(i);
				dewdrop:AddLine('text', c, 'value', c, 'hasArrow', true)
			end
		elseif value==-3 then -- Animated/...
			dewdrop:AddLine('text', L['Not animated'], 'value', 0, 'hasArrow', true)
			dewdrop:AddLine('text', L['|cffa335eeAnimated|r'], 'value', 1, 'hasArrow', true)
			dewdrop:AddLine('text', L['|cffff8000Voiced|r'], 'value', 2, 'hasArrow', true)
			dewdrop:AddLine('text', L['|cff1eff00Animated + Voiced|r'], 'value', 3, 'hasArrow', true)
		elseif value==-4 then -- Custom
			dewdrop:AddLine('text', L['Add...'], 'value', 'add', 'hasArrow', true)
			for _, k in ipairs(self:GetCustoms()) do
				self:AddEmoteToMenu(k)
			end			
		elseif value==0 then -- Options
			self:_AddMenuToggle(L["Show Command"],'showCommand')
			self:_AddMenuToggle(L["Simple Tablet"],'simpleTablet')
			self:_AddMenuToggle(L["Simple Menu"],'simpleMenu')
		else
			for k2, v2 in pairs(EL_Emotes) do
				if value==-1 then
					self:AddEmoteToMenu(k2)
				else
					if v2.types~=nil then
						for k3, v3 in pairs(v2.types) do
							if (value == v3) then
								self:AddEmoteToMenu(k2)
								break
							end		
						end
					end
				end
			end
		end
	elseif level==3 then
		if v1==-2 then -- alpha
			c=string.lower(value);	
			for k2, v2 in pairs(EL_Emotes) do
				if strsub(k2,1,1)==c then
					self:AddEmoteToMenu(k2)
				end
			end
		end
		if v1==-3 then -- animated
			for k2, v2 in pairs(EL_Emotes) do
				if k2.react==value then
					self:AddEmoteToMenu(k2)
				end
			end
		end
		

		if v1==-4 then -- custom
			if value=="add" then
				dewdrop:AddLine('text', L['<Target>, <He>, <His>, <he>, <his>'], 'disabled', true)
				dewdrop:AddLine('text', L['Untargeted Text...'], 'editBoxText', self.cUText, 'hasEditBox', true, 'hasArrow', true, 'editBoxFunc', function(v) self.cUText=v end)
				dewdrop:AddLine('text', L['Targeted Text...'], 'editBoxText', self.cTText, 'hasEditBox', true, 'hasArrow', true, 'editBoxFunc', function(v) self.cTText=v end)
				dewdrop:AddLine('text', L['Short Name'], 'editBoxText', self.cSText, 'hasEditBox', true, 'hasArrow', true, 'editBoxFunc', function(v) self.cSText=v end)
				dewdrop:AddLine('text', L['Add!'], 'func',
					function()
						local id="c-"..string.lower(gsub(self.cUText,"[^a-z]",""))
						self.db.profile.customs[id]={self.cUText, self.cTText,self.cSText}
						self.cUText=""
						self.cTText=""
						self.cSText=""
						self:UpdateCustoms()
						dewdrop:Refresh(2)
					end,
					'disabled', (self.cUText=="" or self.cTText=="" or self.cSText=="")
					)
			else
				dewdrop:AddLine('text', L['Untargeted Text...'], 'editBoxText', self.db.profile.customs[v1][1], 'hasEditBox', true, 'hasArrow', true, 'editBoxFunc', function(v) self.db.profile.customs[v1][1]=v; EmoteFu:UpdateCustoms() end)
				dewdrop:AddLine('text', L['Targeted Text...'], 'editBoxText', self.db.profile.customs[v1][2], 'hasEditBox', true, 'hasArrow', true, 'editBoxFunc', function(v) self.db.profile.customs[v1][2]=v; EmoteFu:UpdateCustoms() end)
			end
		end
	end
end

function EmoteFu:UpdateCustoms()
	local killThese={}
	local k,v
	for k in pairs(EL_Emotes) do
		if EL_Emotes[k].custom then killThese[k]=1 end
	end
	for k in pairs(killThese) do EL_Emotes[k]=nil end
	for k,v in pairs(self.db.profile.customs) do
		EL_Emotes[k]={ none=v[1], target=v[2], react = 0, custom = 1, short=v[3] }
	end
	dewdrop:Refresh(2)
end

function EmoteFu:DeleteCustom(k)
	self.db.profile.customs[k]=nil
	EL_Emotes[k]=nil
	self:UpdateCustoms()
end

function EmoteFu:GetOnDemandText(v2,hasTarget)
	local color;
	local flag = nil;
	local returnCode;
	local emoteText;
	
	if (hasTarget) then emoteText = v2.target else emoteText = v2.none end
	
	if v2.custom then
		emoteText = UnitName("player").." "..emoteText; -- custom emote
	end
	
	if (v2.react == 0) then -- None (text only) White
		color = "fffefefe";
	elseif (v2.react == 1) then -- Animated - Purple
		color = "ffa335ee";
		flag = L["A"];
	elseif (v2.react == 2) then -- Voice - Orange
		color = "ffff8000";
		flag = L["V"];
	elseif (v2.react == 3) then -- Both - Green
		color = "ff1eff00";
		flag = L["AV"];
	else 	-- Grey (Unknown)
		color = "ff9d9d9d";
	end	

	returnCode = "|c" .. color .. emoteText .. FONT_COLOR_CODE_CLOSE;
	if (flag) then returnCode = returnCode.." ["..flag.."]"; end
	return returnCode;
end

function EmoteFu:HandleModClick(k2)
	if (k2) then
		if IsShiftKeyDown() then
			if self.db.profile.favs[k2]~=nil then
				self.db.profile.favs[k2]=nil
			else
				self.db.profile.favs[k2]=1
			end
			dewdrop:Refresh(1)
			self:UpdateTooltip()
			return;
		end
		if EL_Emotes[k2].custom then -- Custom emote
			local emoteText;
			if IsControlKeyDown() then
				self:DeleteCustom(k2)
				return
			end
			self:UpdateTInfo()
			if self.tinfo.hasTarget then
				emoteText = EL_Emotes[k2].target;
			else
				emoteText = EL_Emotes[k2].none;
			end
			info = self:ReplaceTextPlaceholders(info);
			SendChatMessage(emoteText,"EMOTE");
		else
			emoteToken = string.upper(EL_Emotes[k2].token or k2);
			DoEmote(emoteToken);
		end
		dewdrop:Close()
	end
end

function EmoteFu:OnTooltipUpdate()
	local txt
	self:UpdateTInfo()
	tablet:SetTitle(L["EmoteFu"])
	local show_cmd = self.db.profile.showCommand and not self.db.profile.simpleTablet
	local cat;
	if show_cmd then
		cat = tablet:AddCategory(
			'columns', 3,
			'child_textR', 1, 'child_textG', 1, 'child_textB', 0,
			'child_text2R', 1, 'child_text2G', 1, 'child_text2B', 1)
	else
		cat = tablet:AddCategory(
			'columns', 1,
			'child_textR', 1,'child_textG', 1,'child_textB', 1)
	end
	for _, k in ipairs(self:GetFavs()) do
		if self.db.profile.simpleTablet then
			if EL_Emotes[k].custom then
				txt=capitalize(EL_Emotes[k].short)
			else
				txt=capitalize(k)
			end
			if self.tinfo.hasTarget then txt=txt.." "..self.tinfo.hasTarget end
		else
			txt=self:FormatEmoteText(k)
		end
		if show_cmd then
			local slshCmd = EL_Emotes[k].custom and L["Custom"] or ("/"..k)
			cat:AddLine(
				'text',slshCmd,
				'text2',txt,'justify2',"LEFT",
				'func',function(k2) self:HandleModClick(k2) end,'arg1',k)
		else
			cat:AddLine(
				'text',txt,'wrap',1,
				'func',function(k2) self:HandleModClick(k2) end,'arg1',k)
		end
	end	
end

function EmoteFu:OnEnable()
	self:RegisterEvent("PLAYER_TARGET_CHANGED")
	self:UpdateCustoms()
	self.cUText=""
	self.cTText=""
end

function EmoteFu:PLAYER_TARGET_CHANGED()
	self:UpdateTooltip()
end
