---------------------------------------------------------------------------------
--
-- Prat - A framework for World of Warcraft chat mods
--
-- Copyright (C) 2006-2007  Prat Development Team
--
-- This program is free software; you can redistribute it and/or
-- modify it under the terms of the GNU General Public License
-- as published by the Free Software Foundation; either version 2
-- of the License, or (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program; if not, write to:
--
-- Free Software Foundation, Inc., 
-- 51 Franklin Street, Fifth Floor, 
-- Boston, MA  02110-1301, USA.
--
--
-------------------------------------------------------------------------------



--[[
Name: PratChatLink
Revision: $Revision: 28408 $
Author(s): Krtek (krtek4@gmail.com)
           Sylvanaar (sylvanaar@mindspring.com)
Inspired by: Cirk's Chatmanager by Cirk
             ChatLink by Yrys
Website: http://www.wowace.com/files/index.php?path=Prat/
Documentation: http://www.wowace.com/wiki/Prat/Integrated_Modules#ChatLink
Subversion: http://svn.wowace.com/wowace/trunk/Prat/
Discussions: http://groups.google.com/group/wow-prat
Issues and feature requests: http://code.google.com/p/prat/issues/list
Description: Module for Prat that shows item links in chat channels.
Dependencies: Prat
]]

-- set prat module name
local PRAT_MODULE = Prat:RequestModuleName("PratChatLink")

-- define localized strings
local L = AceLibrary("AceLocale-2.2"):new(PRAT_MODULE)

L:RegisterTranslations("enUS", function() return {
    ["ChatLink"] = true,
    ["Chat channel item link options."] = true,
    ["cm_name"] = "ChatManager",
    ["cm_desc"] = "Toggle sending items in Cirk\" ChatManager format.",
    ["clink_name"] = "ChatLink",
    ["clink_desc"] = "Toggle sending items in ChatLink format.",
} end)

L:RegisterTranslations("deDE", function() return {
    ["ChatLink"] = "ChatLink",
    ["Chat channel item link options."] = "Chat Kanal Item Link Optionen.",
    ["cm_name"] = "Chat Manager",
    ["cm_desc"] = "Aktiviere das Senden von Items im Cirk\" ChatManager Format.",
    ["clink_name"] = "Chat Link",
    ["clink_desc"] = "Aktiviere das Senden von items im ChatLink Format.",
} end)

L:RegisterTranslations("esES", function() return {
    ["ChatLink"] = "Enlace de Chat",
    ["Chat channel item link options."] = "Opciones de enlace de objeto en un canal de chat",
    ["cm_name"] = "ChatManager",
    ["cm_desc"] = "Determina si se envian los objetos en el formato Cirk\" ChatManager",
    ["clink_name"] = "Enlace de Chat",
    ["clink_desc"] = "Activa y desactiva los objetos en formato Enlace de Chat.",
} end)

L:RegisterTranslations("koKR", function() return {
    ["ChatLink"] = "대화링크",
    ["Chat channel item link options."] = "대화 채널 아이템 링크 설정입니다.",
    ["cm_name"] = "ChatManager",
    ["cm_desc"] = "Cirk\" Chatmanager 형식으로 아이템을 전송합니다.",
    ["clink_name"] = "ChatLink",
    ["clink_desc"] = "ChatLink 형식으로 아이템을 전송합니다.",
} end)

L:RegisterTranslations("zhCN", function() return {
    ["ChatLink"] = "聊天链接",
    ["Chat channel item link options."] = "聊天频道物品链接选项。",
    ["cm_name"] = "聊天管理",
    ["cm_desc"] = "切换以 Cirk\" 聊天管理模式发送物品。",
    ["clink_name"] = "聊天链接",
    ["clink_desc"] = "切换聊天链接物品发送格式。",
} end)

L:RegisterTranslations("zhTW", function() return {
    ["ChatLink"] = "聊天鏈結",
    ["Chat channel item link options."] = "聊天頻道物品鏈結選項。",
    ["cm_name"] = "聊天管理",
    ["cm_desc"] = "切換為 Cirk\" ChatManager 格式。",
    ["clink_name"] = "聊天鏈結",
    ["clink_desc"] = "切換為 ChatLink 格式。",
} end)

L:RegisterTranslations("frFR", function() return {
    ["ChatLink"] = "Liens",
    ["Chat channel item link options."] = "Options des liens d'objets dans les chats.",
    ["cm_name"] = "ChatManager",
    ["cm_desc"] = "Active l'envoi des liens d'objet au format de Cirk\" ChatManager.",
    ["clink_name"] = "ChatLink",
    ["clink_desc"] = "Active l'envoi des liens d'objets au format ChatLink.",
} end)

-- get prat module categories
local cat = Prat.Categories

-- create prat module
Prat_ChatLink = Prat:NewModule(PRAT_MODULE)
Prat_ChatLink.revision = tonumber(string.sub("$Revision: 28408 $", 12, -3))

-- define key module values
Prat_ChatLink.moduleName = L["ChatLink"]
Prat_ChatLink.moduleDesc = L["Chat channel item link options."]
Prat_ChatLink.consoleName = "chatlink"
Prat_ChatLink.guiName = L["ChatLink"]
Prat_ChatLink.Categories = { cat.LINK, cat.TEXT, cat.FILTER, cat.BEHAVIOR }

-- Set this to true to use Prat Event Support
Prat_ChatLink.supportsPratEvents = true

-- define the default db values
Prat_ChatLink.defaultDB = {
    on = false,
    clink = true,
    cm = false,
}
-- build the options menu using prat templates
Prat_ChatLink.toggleOptions = {
    clink = 180,
    cm = 190
}
-- create a moduleOptions stub (for setting self.moduleOptions)
Prat_ChatLink.moduleOptions = {}

--[[------------------------------------------------
    Module Event Functions
------------------------------------------------]]--

-- things to do when the module is enabled
function Prat_ChatLink:OnModuleEnable()
    -- registry events
    self:RegisterEvent("Prat_PreAddMessage")
    -- what da hook gon be?
    self:Hook("SendChatMessage", true)
end

-- things to do when the module is disabled
function Prat_ChatLink:OnModuleDisable()
    -- unregister events
    self:UnregisterAllEvents()
    -- unhook functions
    self:UnhookAll()
end

--[[------------------------------------------------
    Core Functions
------------------------------------------------]]--

-- add item link with a prat event implementation
function Prat_ChatLink:Prat_PreAddMessage(message, frame, t, r, g, b)
    message.MESSAGE = self:ProcessText(message.MESSAGE)
end

function Prat_ChatLink:SendChatMessage(msg, chatType, language, channel)
    if msg and (chatType == "CHANNEL") then
        local _, chanName = GetChannelName(channel)
        if chanName and
            not string.find (chanName, "General - ") and
            not string.find (chanName, "Trade - ") and
            not string.find (chanName, "LookingForGroup") and
            not string.find (chanName, "LocaleDefense - ") and
            not string.find (chanName, "WorldDefense")
        then
            msg = Prat_ChatLink:CreateLink(msg);
        end
    end
    self.hooks.SendChatMessage(msg, chatType, language, channel)
end

-- Utility Function
function Prat_ChatLink:ProcessText(text)
    if (self.db.profile.clink) then
        return self:ChatLink_Decompose(text)
    end
    if text then
        -- Chatmanager [Thick Furry Mane]{4583:0:0:0}
        text = Prat_ChatLink:DecomposeCMLink(text, "%[([^%[^%]]-)%]{(%d+):(%d+):(%d+):(%d+)}(\b*)")
        -- Code from ChatLink
        text = string.gsub (text, "{CLINK:item:(%x+):(%d-:%d-:%d-:%d-:%d-:%d-:%d-:%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
        text = string.gsub (text, "{CLINK:enchant:(%x+):(%d-):([^}]-)}", "|c%1|Henchant:%2|h[%3]|h|r")
        -- For backward compatibility (yeah, I should have done it before...).
        text = string.gsub (text, "{CLINK:(%x+):(%d-:%d-:%d-:%d-:%d-:%d-:%d-:%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
        -- Forward compatibility, for future clink structure changes.
        text = string.gsub (text, "{CLINK(%d):%[?([^:}%]]-)%]?:([^:}]-)[^}]-}", "%2")
        return text
    end
end

function Prat_ChatLink:CreateLink(link)
    local pattern = "|c(%x+)|Hitem:(%d+):(%d+):(%d+):(%d+)|h%[(.-)%]|h|r"
    if (self.db.profile.clink) then
        return self:ChatLink_Compose(link)
    elseif (self.db.profile.chatmanager) then return Prat_ChatLink:CreateCMLink(link, pattern)
    else return link end
end

-- Inspired from Cirk"s Chatmanager
local _rarityConvertToColor = {}
local _rarityLookupByColor = {}

for rarity = 0, 6 do
    local _, _, _, itemColor = GetItemQualityColor(rarity);
    if (itemColor) then
        _rarityConvertToColor[rarity] = itemColor;
        _rarityLookupByColor[string.sub(itemColor, 3)] = rarity;
    end
end

function Prat_ChatLink:DecomposeCMLink(link, pattern)
    local function gsubDecomposeCMLink(name, i1, i2, i3, i4, rS)
        local itemString = "item:"..i1..":"..i2..":"..i3..":"..i4;
        local itemName, itemLink, itemRarity = GetItemInfo(itemString);
        if (itemName and itemLink and itemRarity) then
            local itemColor = _rarityConvertToColor[tonumber(itemRarity)];
            if (not itemColor) then
                itemColor = "";
            end
            return itemColor.."|H"..itemLink.."|h["..itemName.."]|h|r";
        end
        itemRarity = string.len(rS) - 1;
        if (itemRarity >= 0) then
            local itemColor = _rarityConvertToColor[tonumber(itemRarity)];
            if (not itemColor) then
                itemColor = "";
            end
            return itemColor.."|H"..itemString.."|h["..name.."]|h|r";
        end
        return "|H"..itemString.."|h["..name.."]|h|r";
    end
    return string.gsub(link, pattern, gsubDecomposeCMLink)
end

function Prat_ChatLink:CreateCMLink(link, pattern)
    local function gsubCMLink(cS, i1, i2, i3, i4, name)
        local itemString = "item:"..i1..":"..i2..":"..i3..":"..i4;
        local _, _, itemRarity = GetItemInfo(itemString);
        if (not itemRarity) then
            -- Perform reverse color lookup to get rarity instead
            itemRarity = _rarityLookupByColor[cS];
        end
        if (itemRarity) then
            return "["..name.."]{"..i1..":"..i2..":"..i3..":"..i4.."}"..string.rep("\b", tonumber(itemRarity) + 1);
        end
        return "["..name.."]{"..i1..":"..i2..":"..i3..":"..i4.."}";
    end
    return string.gsub(link, pattern, gsubCMLink)
end

-- CREDIT TO: Yrys - Hellscream, author of ChatLink, the following code copied verbatim

-- Turn CLINKs into normal item and enchant links.
function Prat_ChatLink:ChatLink_Decompose (chatstring)
    if chatstring then
		chatstring = string.gsub (chatstring, "{CLINK:item:(%x+):(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
		chatstring = string.gsub (chatstring, "{CLINK:enchant:(%x+):(%-?%d-):([^}]-)}", "|c%1|Henchant:%2|h[%3]|h|r")
        -- For backward compatibility (yeah, I should have done it before...).
		chatstring = string.gsub (chatstring, "{CLINK:(%x+):(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-):([^}]-)}", "|c%1|Hitem:%2|h[%3]|h|r")
        -- Forward compatibility, for future clink structure changes.
        chatstring = string.gsub (chatstring, "{CLINK(%d):%[?([^:}%]]-)%]?:([^:}]-)[^}]-}", "%2")
    end
    return chatstring
end

-- Turn item and enchant links into CLINKs.
function Prat_ChatLink:ChatLink_Compose (chatstring)
    if chatstring then
--      1.10 item links: to possibly be reactivated in a future version.
--      chatstring = string.gsub (chatstring, "|c(%x+)|H(item):(%d-):(%d-):(%d-):(%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4:%5:%6:%7}")
--      Old item links: backward compatibility.
		chatstring = string.gsub (chatstring, "|c(%x+)|Hitem:(%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-:%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%1:%2:%3}")
		chatstring = string.gsub (chatstring, "|c(%x+)|H(enchant):(%-?%d-)|h%[([^%]]-)%]|h|r", "{CLINK:%2:%1:%3:%4}")
    end
    return chatstring
end