--## Version: 3.10.1  ## Author: SDPhantom  ## SavedVariables: ChatLinkIcons_Options
--[[	ChatLinkIcons - Localization
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------
local CLI = {}

----------------------------------
--[[	Localization Table	]]
----------------------------------
local Localization={
	enUS={--	Native locale by SDPhantom
--		Options Panel
		Options_ByAuthor_Format="by %s";
		Options_Addon_Name="ChatLinkIcons";

--		Options Panel (Settings)
		OptionsSetting_Links_Achievement="Achievements";
		OptionsSetting_Links_BattlePet="Battle Pets";
		OptionsSetting_Links_BattlePet_Ability="Abilities";
		OptionsSetting_Links_CalendarEvent="Calendar Events";
		OptionsSetting_Links_GarrisonFollower="Garrison Followers";
		OptionsSetting_Links_GarrisonFollower_Ability="Abilities";
		OptionsSetting_Links_Item="Items";
		OptionsSetting_Links_Player="Players";
		OptionsSetting_Links_Player_RaceGender="Race/Gender";
		OptionsSetting_Links_Player_Class="Class";
		OptionsSetting_Links_Spell="Spells";
		OptionsSetting_Links_Tradeskill="Tradeskills";
		OptionsSetting_Links_Transmog="Transmog";

		OptionsSetting_Integration_Format="%1$s Integration |cff%2$s(%3$s)|r";--	Receives title/name, color code, and load state
		OptionsSetting_Integration_Loaded="Loaded";
	};
	zhCN={--	Translated by Loukky
--		Options Panel
		Options_ByAuthor_Format="由 %s";
		Options_Addon_Name="|cffff6699[聊天]|r信息图标";

--		Options Panel (Settings)
		OptionsSetting_Links_Achievement="成就";
		OptionsSetting_Links_BattlePet="战斗宠物";
		OptionsSetting_Links_BattlePet_Ability="能力";
		OptionsSetting_Links_CalendarEvent="日历事件";
		OptionsSetting_Links_GarrisonFollower="要塞追随者";
		OptionsSetting_Links_GarrisonFollower_Ability="能力";
		OptionsSetting_Links_Item="物品";
		OptionsSetting_Links_Player="玩家";
		OptionsSetting_Links_Player_RaceGender="种族/性别";
		OptionsSetting_Links_Player_Class="职业";
		OptionsSetting_Links_Spell="技能";
		OptionsSetting_Links_Tradeskill="商业技能";
		OptionsSetting_Links_Transmog="幻化";

		OptionsSetting_Integration_Format="%1$s 一体化 |cff%2$s(%3$s)|r";--	Receives title/name, color code, and load state
		OptionsSetting_Integration_Loaded="已加载";
	};
};

setmetatable(Localization.enUS,{__index=function(t,k) return k; end});
CLI.Localization=Localization[GetLocale()] or Localization.enUS;
if CLI.Localization~=Localization.enUS then setmetatable(CLI.Localization,{__index=Localization.enUS}); end

----------------------------------
--[[	Localization Loader	]]--	Nothing to localize below this line
----------------------------------

--[[	ChatLinkIcons - Callback Handler
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------
local CallbackMeta={__index={}};

CallbackMeta.__index.IsRegistered=tContains;

function CallbackMeta.__index:Register(func)
	if not tContains(self,func) then table.insert(self,func); end
end

function CallbackMeta.__index:Unregister(func)
	local index=tIndexOf(self,func); if index then
		table.remove(self,index);
	end
end

function CallbackMeta.__index:Fire(...)
	for _,func in ipairs(self) do
		xpcall(func,CallErrorHandler,...);
	end
end

CallbackMeta.__call=CallbackMeta.__index.Fire;

function CLI.Callbacks_New() return setmetatable({},CallbackMeta); end


--[[	ChatLinkIcons - Event Handler
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------
local CallbackObjectClosureCache=setmetatable({},{__mode="kv",__index=function(t,k)
	local func=function(...) return k(...); end
	t[k]=func; return func;
end});

function CLI.Events_RegisterEvent(event,func)
--	CallbackRegistry doesn't like non-function callbacks (ex. tables and userdata with a __call metamethod)
	do	local type=type(func);
		if type~="function" then
			assert(type=="table" or type=="userdata","Invalid callback type: "..type);
			local meta=assert(getmetatable(func),"Callback object doesn't have a metatable");
			assert(meta.__call,"Callback object doesn't have a \"__call\" metamethod");
			func=CallbackObjectClosureCache[func];
		end
	end

	EventRegistry:RegisterFrameEventAndCallback(event,func);
end

function CLI.Events_UnregisterEvent(owner,event)
--	Owner is an arbitrary value created by CallbackRegistry passed to the callback as Self
	EventRegistry:UnregisterFrameEventAndCallback(event,owner);
end


--[[	ChatLinkIcons - Player Cache
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

CLI.PlayerCache_OnPlayerAdded=CLI.Callbacks_New();

local ServerTag;
local PlayerCache={};

local GuildRoster=GuildRoster or C_GuildInfo.GuildRoster;--	Blizzard removed the legacy location of this function in 9.0 while C_GuildInfo isn't available in Classic

------------------
--[[	API	]]
------------------
local function NormalizePlayerName(name) return (name:find("%-") and name) or (ServerTag and ("%s-%s"):format(name,ServerTag)); end

function CLI.PlayerCache_AddPlayer(name,guid)
	if not (name and guid) then return; end
	name=NormalizePlayerName(name);
	if name and PlayerCache[name]~=guid then
		PlayerCache[name]=guid;
		CLI.PlayerCache_OnPlayerAdded:Fire();
	end
end

function CLI.PlayerCache_GetPlayerGUID(name)
	if not name then return; end
	name=NormalizePlayerName(name);
	return name and PlayerCache[name];
end

--------------------------
--[[	Event Handlers	]]
--------------------------
CLI.Events_RegisterEvent("PLAYER_LOGIN",function(self,...)
	ServerTag=GetNormalizedRealmName();--	Update server tag
	CLI.PlayerCache_AddPlayer(UnitName("player"),UnitGUID("player"));--	Register player GUID
	C_FriendList.ShowFriends();--	Request friend list
	GuildRoster();--	Request guild roster

	CLI.Events_UnregisterEvent(self,"PLAYER_LOGIN");
end);

CLI.Events_RegisterEvent("PLAYER_GUILD_UPDATE",function(self)
	GuildRoster();--	Player joined/left guild
end);

CLI.Events_RegisterEvent("FRIENDLIST_UPDATE",function(self)
	for i=1,C_FriendList.GetNumFriends() do
		local info=C_FriendList.GetFriendInfoByIndex(i);
		if info and info.name and info.guid then CLI.PlayerCache_AddPlayer(info.name,info.guid); end--	Register friend
	end
end);

CLI.Events_RegisterEvent("GUILD_ROSTER_UPDATE",function(self,...)
--	(...) is true if the a refresh is needed, false if a refresh has been done
	if (...) then GuildRoster(); else
		for i=1,(GetNumGuildMembers()) do
			local name,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,guid=GetGuildRosterInfo(i);
			if name and guid then CLI.PlayerCache_AddPlayer(name,guid); end--	Register guildmate
		end
	end
end);

do--	Chat Events
	local function OnChatEvent(self,_,name,_,_,_,_,_,_,_,_,_,guid)
		if not canaccessvalue or (canaccessvalue(name) and canaccessvalue(guid)) then
			if (name or "")~="" and (guid or "")~="" then CLI.PlayerCache_AddPlayer(name,guid); end
		end
	end

--	CHAT_MSG_CHANNEL is registered by ChatFrame_OnLoad() and isn't included in the event tables
	if not ChatTypeGroupInverted.CHAT_MSG_CHANNEL then CLI.Events_RegisterEvent("CHAT_MSG_CHANNEL",OnChatEvent); end
	for event in pairs(ChatTypeGroupInverted) do
		if event:find("^CHAT_MSG_") then CLI.Events_RegisterEvent(event,OnChatEvent); end
	end
end


--[[	ChatLinkIcons - Options
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

local Title= CLI.Localization.Options_Addon_Name;        --select(2,C_AddOns.GetAddOnInfo(Name)):gsub("%s*v?[%d%.]+$","");
CLI.Options_OnOptionsUpdate=CLI.Callbacks_New();

----------------------------------
--[[	Options Variable Setup	]]
----------------------------------
local Defaults={Options_SaveVersion=2};
CLI.Options=Defaults;--	Give other modules direct access to defaults while loading

----------------------------------
--[[	Table Copy Function	]]
----------------------------------
local function CopySettings(source,target,overwritemode)
--	Recursively copies source into target, preserving shared keys unless overwrite is set
--	OverwriteMode is true/false/nil
--		true = wipe	false = overwrite	nil = preserve

	if type(source)~="table" then return source; end
	if type(target)~="table" then target={}; end
	if overwritemode then table.wipe(target); end

	local stack={source};
	local registry={[source]=target};

	while #stack>0 do
		local source=table.remove(stack,1);
		local target=registry[source];

		for k,v in pairs(source) do
			local targetval=target[k];
			if type(v)=="table" then--	Tables are merged, non-tables are automatically overwritten
				local newval=registry[v];
				if not newval then
					newval=(type(targetval)=="table" and targetval or {});
					if overwritemode then table.wipe(newval); end
					registry[v]=newval;
					table.insert(stack,v);
				end

				target[k]=newval;
			elseif overwritemode~=nil or targetval==nil then target[k]=v; end--	Preserve existing values unless overwrite flag set
		end
	end

	return target;
end

--------------------------
--[[	Options Panel	]]
--------------------------
local Panel=CreateFrame("Frame"); do
	Panel:Hide();

	local title=Panel:CreateFontString(nil,"OVERLAY","GameFontNormalLarge");
	title:SetPoint("TOP",0,-12);
	title:SetText(Title);

	local author=Panel:CreateFontString(nil,"OVERLAY","GameFontNormalSmall");
	author:SetPoint("TOP",title,"BOTTOM",0,0);
	author:SetTextColor(1,0.5,0.25);
	author:SetText("SDPhantom");  --CLI.Localization.Options_ByAuthor_Format:format(C_AddOns.GetAddOnMetadata(Name,"Author"))

	local version=Panel:CreateFontString(nil,"OVERLAY","GameFontNormalSmall");
	version:SetPoint("TOPLEFT",title,"TOPRIGHT",4,0);
	version:SetTextColor(0.5,0.5,0.5);
	version:SetText("v3.10.1"); --..C_AddOns.GetAddOnMetadata(Name,"Version")
end

--------------------------
--[[	Event Handlers	]]
--------------------------
Panel:RegisterEvent("ADDON_LOADED");
Panel:SetScript("OnEvent",function(self,event,...)
	if event=="ADDON_LOADED" and (...)=="OrzUI" then
		ChatLinkIcons_Options=CopySettings(Defaults,ChatLinkIcons_Options or {}
--			Cast to either true for wipe or nil for preserve
			,ChatLinkIcons_Options and (ChatLinkIcons_Options.Options_SaveVersion~=Defaults.Options_SaveVersion or nil)
		);

		CLI.Options=ChatLinkIcons_Options;
		CLI.Options_OnOptionsUpdate:Fire();
		self:UnregisterEvent(event);
	end
end);

--------------------------
--[[	Options API	]]
--------------------------
local OptionButtonList={};
local OptionButtonLookup={};

local function RefreshOptionButtons()
	local stack={};
	for _,button in ipairs(OptionButtonList) do if not button.Parent then table.insert(stack,button); end end
	for _,parent in ipairs(stack) do for _,child in ipairs(parent) do table.insert(stack,child); end end
	for _,button in ipairs(stack) do button:Refresh(); end
end

function CLI.Options_LookupOptionButton(key) return OptionButtonLookup[key]; end

do--	CLI.Options_CreateOptionButton(anchorgroup,key,text,defaultval,xoff)
	local Padding=-8;
	local AnchorGroup={
		{"TOPLEFT",Panel,"TOPLEFT",24,-48};
		{"TOPLEFT",Panel,"TOP",0,-48};
	};

--	Internal API
	local function OptionButton_Refresh(self)
		self:SetEnabled(not self.Parent or (self.Parent:IsEnabled() and CLI.Options[self.Parent.Key]~=false));
		self:SetChecked(CLI.Options[self.Key]);
	end

--	Scripts
	local function OptionButton_OnClick(self)
		CLI.Options[self.Key]=self:GetChecked();

--		Update Dependants
		local stack={self}; repeat
			for _,child in ipairs(table.remove(stack,1)) do
				child:Refresh();
				if #child>0 then table.insert(stack,child); end
			end
		until #stack<=0

		CLI.Options_OnOptionsUpdate:Fire();
	end

--	Generator
	function CLI.Options_CreateOptionButton(parentkey,optionkey,text)
		local parent,anchor;
		if type(parentkey)=="number" then
			anchor=assert(AnchorGroup[parentkey],"AnchorID out of bounds");
		else
			parent=assert(OptionButtonLookup[parentkey],"Undefined parent key");
			anchor=parent.Anchor;
		end

		local button=CreateFrame("CheckButton",nil,Panel,"UICheckButtonTemplate");
		local level=parent and parent.Level+1 or 1;
		local point,relframe,relpoint,x,y=unpack(anchor);

		button:SetPoint(point,relframe,relpoint,x+(level-1)*(button:GetWidth()+Padding),y);

		button:SetFontString(button.Text);
		button:SetNormalFontObject(GameFontNormalSmall);
		button:SetHighlightFontObject(GameFontHighlightSmall);
		button:SetDisabledFontObject(GameFontDisableSmall);
		button:SetText(text or CLI.Localization["OptionsSetting_"..optionkey]);
		button:SetHitRectInsets(4,6-button.Text:GetWidth(),4,4);

		button:SetScript("OnClick",OptionButton_OnClick);

		button.Anchor=anchor;
		button.Parent=parent;
		button.Level=level;
		button.Key=optionkey;

		button.Refresh=OptionButton_Refresh;
		if parent then table.insert(parent,button); end

		anchor[5]=y-button:GetHeight()-Padding;
		table.insert(OptionButtonList,button);
		OptionButtonLookup[optionkey],OptionButtonLookup[button]=button,optionkey;

		return button;
	end
end

------------------------------------------
--[[	Panel Registration & Callbacks	]]
------------------------------------------
local OptionCache={};
local function Options_Cancel()
	CopySettings(OptionCache,CLI.Options,false);
	RefreshOptionButtons();
	CLI.Options_OnOptionsUpdate:Fire();
end

local function Options_Default()
	CopySettings(Defaults,CLI.Options,true);
	CopySettings(Defaults,OptionCache,true);
	RefreshOptionButtons();
	CLI.Options_OnOptionsUpdate:Fire();
end

local function Options_Refresh()
	CopySettings(CLI.Options,OptionCache,true);
	RefreshOptionButtons();
end

--	Panel Registration
if Settings and (Settings.RegisterCanvasLayoutCategory and Settings.RegisterAddOnCategory) then
--	Panel.name=Title;
	Panel.OnCommit=nop;
	Panel.OnDefault=Options_Default;
	Panel.OnRefresh=Options_Refresh;

	local category=Settings.RegisterCanvasLayoutCategory(Panel,Title);
	category.ID=Title;
	Settings.RegisterAddOnCategory(category);
else
	Panel.name=Title;
	Panel.okay=nop;
	Panel.cancel=Options_Cancel;
	Panel.default=Options_Default;
	Panel.refresh=Options_Refresh;
	InterfaceOptions_AddCategory(Panel);
end


--[[	ChatLinkIcons - Link Converter
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

local TextureFunctions={};

function CLI.LinkConverter_RegisterLinkProcessor(type,func)
	if TextureFunctions[type] then
		table.insert(TextureFunctions[type],func);
	else TextureFunctions[type]={func}; end
end

local ConvertCache={};
local function CallLinkProcessors(type,id,text,...)
	local funclist=TextureFunctions[type];
	if not funclist then return; end

	for _,func in ipairs(funclist) do
		local ok,pre,post=xpcall(func,CallErrorHandler,type,id,text,...);
		if ok and (pre or post) then
			if pre then table.insert(ConvertCache,1,pre); end
			if post then table.insert(ConvertCache,post); end
		end
	end
end

local function LinkConverterCallback(link,type,id,text)
	table.insert(ConvertCache,link);
	CallLinkProcessors(type,id,text,(":"):split(id));

	local replace=(#ConvertCache>1 and table.concat(ConvertCache) or nil);
	table.wipe(ConvertCache);
	return replace;
end

function CLI.LinkConverter_ConvertLinks(str)
	if type(str)~="string" or (canaccessvalue and not canaccessvalue(str)) then return str; end

	local fix; str,fix=str:gsub("(|H([^:|]+):([^|]-)|h(.-)|h)",LinkConverterCallback);
	if fix>0 then
--		Fix links with color codes having textures inserted inside them
		repeat str,fix=str:gsub("(|c%x%x%x%x%x%x%x%x)(%s*|T[^|]*|t%s*)","%2%1"); until fix<=0
		repeat str,fix=str:gsub("(%s*|T[^|]*|t%s*)(|r)","%2%1"); until fix<=0
	end
	return str;
end


--[[	ChatLinkIcons - Link Processor Tools
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

local GetSpellTexture=GetSpellTexture or C_Spell.GetSpellTexture;--	Moved in TWW, hasn't happened in Classic yet

local UnknownIconMarkup="|TInterface\\Icons\\INV_Misc_QuestionMark:0|t";

local RaceAtlasMap={
	Scourge="Undead";
	HighmountainTauren="Highmountain";
	LightforgedDraenei="Lightforged";
	ZandalariTroll="Zandalari";
	EarthenDwarf="Earthen";
	Harronir="Haranir";
};

local RaceAtlasMarkupCache; do
	local RaceAtlasPrefixOrder={
		"raceicon128";
		"raceicon";
	};

	RaceAtlasMarkupCache=setmetatable({},{__index=function(t,k)
		for _,prefix in ipairs(RaceAtlasPrefixOrder) do
			local atlas=("%s-%s"):format(prefix,k);
			if C_Texture.GetAtlasInfo(atlas) then
				local markup=CreateAtlasMarkup(atlas);
				t[k]=markup;
				return markup;
			end
		end

		return nil;
	end});
end

local ClassAtlasMarkupCache; do
	local function CreateTextureMarkupFromGrid(file,filew,fileh,x,y,tilew,tileh)
		return CreateTextureMarkup(file,filew,fileh,0,0,GetTexCoordsByGrid(x,y,filew,fileh,tilew,tileh));
	end

	local ManualClassAtlases={
		MONK={"Interface\\GLUES\\CHARACTERCREATE\\UI-CHARACTERCREATE-CLASSES",256,256,3,3,64,64};
	};

	ClassAtlasMarkupCache=setmetatable({},{__index=function(t,k)
		local atlas=GetClassAtlas(k);
		if C_Texture.GetAtlasInfo(atlas) then
			local markup=CreateAtlasMarkup(atlas);
			t[k]=markup;
			return markup;
		end

		if ManualClassAtlases[k] then
			local markup=ManualClassAtlases[k];
			t[k]=markup;
			return markup
		end

		return nil;
	end});
end

function CLI.LinkProcessorTools_CreateTextureMarkup(path) return path and ("|T%s:0|t"):format(tostring(path)); end
function CLI.LinkProcessorTools_CreateTextureMarkupFromItemID(itemid) return itemid and CLI.LinkProcessorTools_CreateTextureMarkup(GetItemIcon(itemid)); end
function CLI.LinkProcessorTools_CreateTextureMarkupFromSpellID(spellid) return spellid and CLI.LinkProcessorTools_CreateTextureMarkup(GetSpellTexture(spellid)); end

function CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerGUID(guid)
	if not guid then return nil; end

--	GenderID is 2=Male 3=Female
	local _,class,_,race,gender=GetPlayerInfoByGUID(guid);

	race,class=
		CLI.Options.Links_Player_Race
			and ((race and gender) and RaceAtlasMarkupCache[("%s-%s"):format(RaceAtlasMap[race] or race,gender==3 and "female" or "male")] or UnknownIconMarkup)
			or nil
		,CLI.Options.Links_Player_Class
			and (class and ClassAtlasMarkupCache[class] or UnknownIconMarkup)
			or nil;
	return (race and class) and race..class or (race or class);
end

function CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerName(name)
	return CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerGUID(CLI.PlayerCache_GetPlayerGUID(name));
end



--[[	Debug: Prints out a list of found race and class atlases
--	Race atlases are shown in a grid comparing variants

function SlashCmdList.CLI_ATLASTEST()
	local classes={};
	local prefixes,races,genders={},{},{};

	for _,atlas in ipairs(C_Texture.GetAtlasElements()) do
		local class=atlas:match("^classicon%-(.*)");
		if class then table.insert(classes,class); end

		local prefix,race,gender=atlas:match("^(raceicon.-)%-(.*)%-(.-)$");
		if prefix and race and gender then
			if not prefixes[prefix] then
				table.insert(prefixes,prefix);
				prefixes[prefix]=true;
			end

			if not races[race] then
				table.insert(races,race);
				races[race]=true;
			end

			if not genders[gender] then
				table.insert(genders,gender);
				genders[gender]=true;
			end
		end
	end

	table.sort(classes);
	table.sort(prefixes);
	table.sort(races);
	table.sort(genders);

	for _,class in ipairs(classes) do print(ClassAtlasMarkupCache[class],class); end
	print("Classes:",#classes);

	print(" ");
	print(table.concat(prefixes," || "));
	for _,race in ipairs(races) do
		local prefixentries={};
		for _,prefix in ipairs(prefixes) do
			local genderentries={};
			for _,gender in ipairs(genders) do
				local atlas=("%s-%s-%s"):format(prefix,race,gender);
				table.insert(genderentries,C_Texture.GetAtlasInfo(atlas) and CreateAtlasMarkup(atlas) or UnknownIconMarkup);
			end
			table.insert(prefixentries,table.concat(genderentries,""));
		end
		print(table.concat(prefixentries,"    "),race);
	end

	print(("Prefixes: %d || Races: %d || Genders: %d"):format(#prefixes,#races,#genders));
end
SLASH_CLI_ATLASTEST1="/cliatlastest";
--]]


--[[	ChatLinkIcons - Achievement Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------
CLI.Options.Links_Achievement=true;

CLI.Options_CreateOptionButton(1,"Links_Achievement");

CLI.LinkConverter_RegisterLinkProcessor("achievement",function(_,_,_,achievementid)--	(type,id,text,...)
	if not CLI.Options.Links_Achievement then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkup(select(10,GetAchievementInfo(tonumber(achievementid))));
end);


--[[	ChatLinkIcons - Battle Pet Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

CLI.Options.Links_BattlePet=true;
CLI.Options.Links_BattlePet_Ability=true;

CLI.Options_CreateOptionButton(1,"Links_BattlePet");
CLI.Options_CreateOptionButton("Links_BattlePet","Links_BattlePet_Ability");

CLI.LinkConverter_RegisterLinkProcessor("battlepet",function(_,_,_,speciesid)--	(type,id,text,...)
	if not CLI.Options.Links_BattlePet then return; end
	local info=C_PetJournal.GetPetInfoBySpeciesID(tonumber(speciesid));
	return info and CLI.LinkProcessorTools_CreateTextureMarkup(select(2,info.speciesIcon));
end);

CLI.LinkConverter_RegisterLinkProcessor("battlePetAbil",function(_,_,_,abilityid)--	(type,id,text,...)
	if not (CLI.Options.Links_BattlePet and CLI.Options.Links_BattlePet_Ability) then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkup(select(2,C_PetJournal.GetPetAbilityInfo(tonumber(abilityid))));
end);

--[[	ChatLinkIcons - Calendar Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

CLI.Options.Links_CalendarEvent=true;

CLI.Options_CreateOptionButton(1,"Links_CalendarEvent");

CLI.LinkConverter_RegisterLinkProcessor("calendarEvent",function(_,_,_,offset,day,index)--	(type,id,text,...)
	if not CLI.Options.Links_CalendarEvent then return; end
	local event=C_Calendar.GetDayEvent(tonumber(offset),tonumber(day),tonumber(index));
	return event and CLI.LinkProcessorTools_CreateTextureMarkup(event.iconTexture);
end);


--[[	ChatLinkIcons - Garrison Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

CLI.Options.Links_GarrisonFollower=true;
CLI.Options.Links_GarrisonFollower_Ability=true;

CLI.Options_CreateOptionButton(1,"Links_GarrisonFollower");
CLI.Options_CreateOptionButton("Links_GarrisonFollower","Links_GarrisonFollower_Ability");

CLI.LinkConverter_RegisterLinkProcessor("conduit",function(type,id,text,conduitid,conduitrank)--	(type,id,text,...)
	if not (CLI.Options.Links_GarrisonFollower and CLI.Options.Links_GarrisonFollower_Ability) then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkupFromSpellID(C_Soulbinds.GetConduitSpellID(tonumber(conduitid),conduitrank and tonumber(conduitrank)));
end);

CLI.LinkConverter_RegisterLinkProcessor("garrfollower",function(_,_,_,followerid)
	if not CLI.Options.Links_GarrisonFollower then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkup(C_Garrison.GetFollowerPortraitIconIDByID(tonumber(followerid)));
end);

CLI.LinkConverter_RegisterLinkProcessor("garrfollowerability",function(_,_,_,abilityid)--	(type,id,text,...)
	if not (CLI.Options.Links_GarrisonFollower and CLI.Options.Links_GarrisonFollower_Ability) then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkup(C_Garrison.GetFollowerAbilityIcon(tonumber(abilityid)));
end);

--[[	ChatLinkIcons - Item Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

CLI.Options.Links_Item=true;

CLI.Options_CreateOptionButton(1,"Links_Item");

CLI.LinkConverter_RegisterLinkProcessor("currency",function(_,_,_,currencyid)--	(type,id,text,...)
	if not CLI.Options.Links_Item then return; end
	local info=C_CurrencyInfo.GetCurrencyInfo(tonumber(currencyid));
	return info and CLI.LinkProcessorTools_CreateTextureMarkup(info.iconFileID);
end);

CLI.LinkConverter_RegisterLinkProcessor("item",function(_,_,_,itemid)--	(type,id,text,...)
	if not CLI.Options.Links_Item then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkupFromItemID(tonumber(itemid));
end);


--[[	ChatLinkIcons - Player Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



CLI.Options.Links_Player=true;
CLI.Options.Links_Player_Race=true;
CLI.Options.Links_Player_Class=false;

CLI.Options_CreateOptionButton(1,"Links_Player");
CLI.Options_CreateOptionButton("Links_Player","Links_Player_Race",CLI.Localization.OptionsSetting_Links_Player_RaceGender);
CLI.Options_CreateOptionButton("Links_Player","Links_Player_Class");

local function PlayerProcessor(_,_,_,name)--	(type,id,text,...)
	if not CLI.Options.Links_Player then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerName(name);
end

CLI.LinkConverter_RegisterLinkProcessor("player",PlayerProcessor);
CLI.LinkConverter_RegisterLinkProcessor("playerCommunity",PlayerProcessor);
CLI.LinkConverter_RegisterLinkProcessor("playerGM",PlayerProcessor);
CLI.LinkConverter_RegisterLinkProcessor("unit",function(_,_,_,guid)--	(type,id,text,...)
	if not CLI.Options.Links_Player then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerGUID(guid);
end);

--[[	Disabled for now; This was always experimental as I've never had a way to reliably test it
local function BNPlayerProcessor(_,_,_,_,bnetaccountid)--	(type,id,text,...)
	if not CLI.Options.Links_Player then return; end

	local client,online,guid;
	if WOW_PROJECT_ID==WOW_PROJECT_MAINLINE then
		local accountinfo=C_BattleNet.GetAccountInfoByID(tonumber(bnetaccountid));
		local gameinfo=accountinfo and accountinfo.gameAccountInfo;
		client,online,guid=gameinfo.clientProgram,gameinfo.isOnline,gameinfo.playerGuid;
	else
		local _,gameaccountid;
		_,_,_,_,_,gameaccountid,client,online=BNGetFriendInfoByID(tonumber(bnetaccountid));
		_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,_,guid=BNGetGameAccountInfo(gameaccountid);
	end

	if not online then return BNet_GetClientEmbeddedTexture(nil); end
	if client~=BNET_CLIENT_WOW or not guid then return BNet_GetClientEmbeddedTexture(client); end

	return CLI.LinkProcessorTools_CreateTextureMarkupFromPlayerGUID(guid);
end

CLI.LinkConverter_RegisterLinkProcessor("BNplayer",BNPlayerProcessor);
CLI.LinkConverter_RegisterLinkProcessor("BNplayerCommunity",BNPlayerProcessor);
--]]


--[[	ChatLinkIcons - Spell Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



CLI.Options.Links_Spell=true;

CLI.Options_CreateOptionButton(1,"Links_Spell");

CLI.LinkConverter_RegisterLinkProcessor("azessence",function(_,_,_,essenceid)--	(type,id,text,...)
	if not CLI.Options.Links_Spell then return; end
	local info=C_AzeriteEssence.GetEssenceInfo(tonumber(essenceid));
	return info and CLI.LinkProcessorTools_CreateTextureMarkup(info.icon);
end);

CLI.LinkConverter_RegisterLinkProcessor("spell",function(_,_,_,spellid)--	(type,id,text,...)
	if not CLI.Options.Links_Spell then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkupFromSpellID(tonumber(spellid));
end);

if WOW_PROJECT_ID==WOW_PROJECT_MAINLINE then
	CLI.LinkConverter_RegisterLinkProcessor("talent",function(_,_,_,talentid)--	(type,id,text,...)
		if not CLI.Options.Links_Spell then return; end
		return CLI.LinkProcessorTools_CreateTextureMarkup(select(3,GetTalentInfoByID(tonumber(talentid))));
	end);
end


--[[	ChatLinkIcons - Tradeskill Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



CLI.Options.Links_Tradeskill=true;

CLI.Options_CreateOptionButton(1,"Links_Tradeskill");

CLI.LinkConverter_RegisterLinkProcessor("enchant",function(_,id,text,enchantid)--	(type,id,text,...)
	if not CLI.Options.Links_Tradeskill then return; end
	CLI.LinkProcessorTools_CreateTextureMarkupFromSpellID(tonumber(enchantid));
end);

CLI.LinkConverter_RegisterLinkProcessor("trade",function(_,id,text,_,spellid)--	(type,id,text,...)
	if not CLI.Options.Links_Tradeskill then return; end
	CLI.LinkProcessorTools_CreateTextureMarkupFromSpellID(tonumber(spellid));
end);


--[[	ChatLinkIcons - Transmog Link Processor
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



CLI.Options.Links_Transmog=true;

CLI.Options_CreateOptionButton(1,"Links_Transmog");

CLI.LinkConverter_RegisterLinkProcessor("transmogappearance",function(_,_,_,sourceid)--	(type,id,text,...)
	if not CLI.Options.Links_Transmog then return; end
	return CLI.LinkProcessorTools_CreateTextureMarkup(select(4,C_TransmogCollection.GetAppearanceSourceInfo(tonumber(sourceid))));
end);

CLI.LinkConverter_RegisterLinkProcessor("transmogillusion",function(_,_,_,illusionid)--	(type,id,text,...)
	if not CLI.Options.Links_Transmog then return; end
	local info=C_TransmogCollection.GetIllusionInfo(tonumber(illusionid));
	return info and CLI.LinkProcessorTools_CreateTextureMarkup(info.icon);
end);


--[[	ChatLinkIcons - Integration Tools
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------


CLI.IntegrationTools_MessageUpdateDispatcher=CLI.Callbacks_New(); do
	CLI.PlayerCache_OnPlayerAdded:Register(CLI.IntegrationTools_MessageUpdateDispatcher);
	CLI.Options_OnOptionsUpdate:Register(CLI.IntegrationTools_MessageUpdateDispatcher);
end

function CLI.IntegrationTools_FormatOptionLabel(addon)
	local name,title,_,_,reason=C_AddOns.GetAddOnInfo(addon);
	return CLI.Localization.OptionsSetting_Integration_Format:format(
		title or name or addon
		,reason and "ff0000" or "00ff00"
		,reason and _G["ADDON_"..reason] or CLI.Localization.OptionsSetting_Integration_Loaded
	);
end


--[[	ChatLinkIcons - Global API Bridge
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------


ChatLinkIcons={};

ChatLinkIcons.ConvertLinks=CLI.LinkConverter_ConvertLinks;
function ChatLinkIcons.RegisterForLinkUpates(func) CLI.IntegrationTools_MessageUpdateDispatcher:Register(func); end
function ChatLinkIcons.UnregisterForLinkUpates(func) CLI.IntegrationTools_MessageUpdateDispatcher:Unregister(func); end


--[[	ChatLinkIcons - DefaultUI Integration
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



------------------------------------------
--[[	ScrollingMessageFrame Hooks	]]
------------------------------------------
local TextCache={};
local FontString_SetText=UIParent:CreateFontString().SetText;

local function ScrollingMessageFrameFontString_SetText(self,str)
	TextCache[self]=str;
	FontString_SetText(self,CLI.LinkConverter_ConvertLinks(str));
--	getmetatable(self).__index.SetText(self,);
end

local function ScrollingMessageFrameFontString_SetFormattedText(self,fmt,...)
	ScrollingMessageFrameFontString_SetText(self,fmt:format(...));
end

local function ScrollingMessageFrameFontString_GetText(self)
	return TextCache[self];
end

local HookedFontStrings={};
local function ScrollingMessageFrame_AcquireFontString(self)
	for fontstring in self.fontStringPool:EnumerateActive() do
		if not HookedFontStrings[fontstring] then
--			hooksecurefunc(fontstring,"SetText",ScrollingMessageFrameFontString_SetText);
--			hooksecurefunc(fontstring,"SetFormattedText",ScrollingMessageFrameFontString_SetFormattedText);

--			Insecure, but as of 10.1.5, the mainline client is having problems with links becoming uninteractable if :SetText() is called in quick succession
			fontstring.SetText=ScrollingMessageFrameFontString_SetText;
			fontstring.SetFormattedText=ScrollingMessageFrameFontString_SetFormattedText;
			fontstring.GetText=ScrollingMessageFrameFontString_GetText;

			HookedFontStrings[fontstring]=true;
		end
	end
end

local HookedFrames={};
function CLI.Integration_DefaultUI_HookScrollingMessageFrame(frame)
	if not HookedFrames[frame] then
		hooksecurefunc(frame,"AcquireFontString",ScrollingMessageFrame_AcquireFontString);
		HookedFrames[frame]=true;
	end
end

CLI.IntegrationTools_MessageUpdateDispatcher:Register(function()
	for frame in pairs(HookedFrames) do frame:MarkDisplayDirty(); end
end);

--------------------------
--[[	ChatFrame Hooks	]]
--------------------------
for i=1,NUM_CHAT_WINDOWS do CLI.Integration_DefaultUI_HookScrollingMessageFrame(_G["ChatFrame"..i]); end
if ChatFrameMixin and ChatFrameMixin.OnLoad then
	hooksecurefunc(ChatFrameMixin,"OnLoad",CLI.Integration_DefaultUI_HookScrollingMessageFrame);
elseif ChatFrame_OnLoad then
	hooksecurefunc("ChatFrame_OnLoad",CLI.Integration_DefaultUI_HookScrollingMessageFrame);
end


--[[	ChatLinkIcons - Pawn Integration
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------



CLI.Options.Integration_Pawn=true;

local Loaded=C_AddOns.IsAddOnLoaded("Pawn");
local Button=CLI.Options_CreateOptionButton(2,"Integration_Pawn",CLI.IntegrationTools_FormatOptionLabel("Pawn"));
Button:SetEnabled(Loaded);
if not Loaded then return; end

local UpgradeIcon=CreateAtlasMarkup("bags-greenarrow");
local function IsItemUpgrade(link)--	Modified PawnIsItemIDAnUpgrade() (Allows full links to compare upgraded items)
	if not (PawnIsLoaded and PawnIsReady() and link) then return nil; end
	local item=PawnGetItemData(link);
	if not item then return nil; end
	return PawnIsItemAnUpgrade(item) and true or false;
end

CLI.LinkConverter_RegisterLinkProcessor("item",function(_,id)
	if CLI.Options.Integrations_Pawn and IsItemUpgrade("item:"..id) then
		return nil,UpgradeIcon;
	end
end);

CLI.Events_RegisterEvent("PLAYER_EQUIPMENT_CHANGED",CLI.IntegrationTools_MessageUpdateDispatcher);


--[[	ChatLinkIcons - WIM Integration
	by SDPhantom
	https://www.wowinterface.com/forums/member.php?u=34145
	https://www.curseforge.com/members/sdphantomgamer/projects	]]
--------------------------------------------------------------------------

if not WIM then return; end


hooksecurefunc(WIM,"CallModuleFunction",function(funcname,frame)
	if funcname=="OnWindowCreated" and frame then
--		Already checks if hooked before
		CLI.Integration_DefaultUI_HookScrollingMessageFrame(frame.widgets.chat_display);
	end
end);
