---------------------------------------------------------------------------------
--
-- 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: AltNames
Revision: $Revision:  24999$
Author(s): Fin (fin@instinct.org)
Website: http://files.wowace.com/Prat/
Documentation: http://www.wowace.com/wiki/Prat/Integrated_Modules#AltNames
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: Allows people's alt characters to be linked to their mains, which will then be displayed next to their names when found in chat messages (default=off).
Dependencies: Prat
]]

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

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

L:RegisterTranslations("enUS", function() return {
	["Start"] = true,
	["AltNames"] = true,
	["quiet"] = true,
	["quiet_name"] = true,
	["quiet_desc"] = "Whether to report to the chat frame or not.",
	["mainpos_name"] = "Main name position",
	["mainpos_desc"] = "Where to display a character's main name when on their alt.",
	["Allows people's alt characters to be linked to their mains, which can then be displayed next to their names when found in chat messages (default=off)."] = true,
	["Main name position"] = true,
	["<alt name> (eg, /altnames del Personyouthoughtwassomeonesaltbutreallyisnt)"] = true,
	["Where to display a character's main name when on their alt."] = true,
	["Left"] = true,
	["Right"] = true,
	["Disabled"] = true,
	["Find characters"] = true,
	["Search the list of linked characters for matching main or alt names."] = true,
	["<search term> (eg, /altnames find fin)"] = true,
	["Link alt"] = true,
	["Link someone's alt character with the name of their main."] = true,
	["link <alt name> <main name> (eg, /altnames link Fin Finjathealtoffin)"] = true,
	["Delete alt"] = true,
	["Delete a character's link to another character as their main."] = true,
	["Be quiet"] = true,
	["Whether to report to the chat frame or not."] = true,
	["You have not yet linked any alts with their mains."] = true,
	["no matches found"] = true,
	["List all"] = true,
	["List all links between alts and their main names."] = true,
	["Imports data from LOKWhoIsWho, if present (drop your SavedVariables\LOKWhoIsWho.lua in the Prat directory to be able to use this)."] = true,
	["LOKWhoIsWho import"] = true,
	["Clear all"] = true,
	["Clear all links between alts and main names."] = true,
	["Colour"] = true,
	["The colour of an alt's main name that will be displayed"] = true,
} end)

-- L:RegisterTranslations("deDE", function() return {
-- } end)
-- L:RegisterTranslations("frFR", function() return {
-- } end)
-- L:RegisterTranslations("esES", function() return {
-- } end)
-- L:RegisterTranslations("koKR", function() return {
-- } end)
-- L:RegisterTranslations("zhCN", function() return {
-- } end)
-- L:RegisterTranslations("zhTW", function() return {
-- } end)

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

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

Prat_AltNames.Alts = {}

-- define key module values
Prat_AltNames.moduleName = L["AltNames"] 	-- module name, eg "ExampleMod"
Prat_AltNames.moduleDesc = L["Allows people's alt characters to be linked to their mains, which can then be displayed next to their names when found in chat messages (default=off)."] 	-- module description

Prat_AltNames.consoleName = string.lower(Prat_AltNames.moduleName)
Prat_AltNames.guiName = Prat_AltNames.moduleName

-- categories. full list here: http://groups-beta.google.com/group/wow-prat/web/prat-categorie
Prat_AltNames.Categories = { cat.NAME, cat.INFO, cat.TEXT }

-- default values for any settings that need them
Prat_AltNames.defaultDB = {
	on	= false,
	quiet	= false,
	alts	= {},
	altidx	= {},
	mainpos	= 'RIGHT',
	colour	= {},
-- 	brackets = { "[", "]", }	-- ?
	}

-- init moduleOoptions (which gets populated by the other
-- various options tables below
Prat_AltNames.moduleOptions = {}

-- any boolean options
Prat_AltNames.toggleOptions = {
	quiet,
	}

function Prat_AltNames:GetModuleOptions()
	self.moduleOptions = {
		name	= self.moduleName,
		desc	= self.moduleDesc,
		type	= "group",
		args = {
			find = {
				name	= L["Find characters"],
				desc	= L["Search the list of linked characters for matching main or alt names."],
				type	= "text",
				usage	= L["<search term> (eg, /altnames find fin)"],
				order	= 110,
				set	= function(q) self:findChars(q) end,
				get	= false,
				},

			link = {
				name	= L["Link alt"],
				desc	= L["Link someone's alt character with the name of their main."],
				type	= "text",
				order	= 120,
				usage	= L["link <alt name> <main name> (eg, /altnames link Fin Finjathealtoffin)"],
				set	= function(argstr) self:addAlt(argstr) end,
				get	= false,
				},

			del = {
				name	= L["Delete alt"],
				desc	= L["Delete a character's link to another character as their main."],
				type	= "text",
				usage	= L["<alt name> (eg, /altnames del Personyouthoughtwassomeonesaltbutreallyisnt)"],
				order	= 130,
				set	= function(altname) self:delAlt(altname) end,
				get	= false,
				confirm	= true,
				},

			quiet = {
				name	= L["Be quiet"],
				desc	= L["Whether to report to the chat frame or not."],
				type	= "toggle",
				order	= 140,

				get	= function() return self.db.profile.quiet end,
				set	= function(v) self.db.profile.quiet = v end,
				},
			listall = {
				name	= L["List all"],
				desc	= L["List all links between alts and their main names."],
				type	= "execute",
				func	= function() self:listAll() end,
				},
			importfromlok = {
				name	= L["LOKWhoIsWho import"],
				desc	= L["Imports data from LOKWhoIsWho, if present (drop your SavedVariables\LOKWhoIsWho.lua in the Prat directory to be able to use this)."],
				type	= "execute",
				func	= function() return self:importFromLOK() end,
				confirm	= true,
				},
			clearall = {
				name	= L["Clear all"],
				desc	= L["Clear all links between alts and main names."],
				type	= "execute",
				func	= function() return self:clearAllAlts() end,
				confirm	= true,
				},
			fixalts = {
				name	= "Fix alts",
				desc	= "Fix corrupted entries in your list of alt anmes.",
				type	= "execute",
				func	= function() return self:fixAlts() end,
				},
			color = {
				name	= L["Colour"],
				get	= function() return self:getColour() end,
				set	= function(nr, ng, nb, na) self.db.profile.colour = { r = nr, g = ng, b = nb } end,
				desc	= L["The colour of an alt's main name that will be displayed"],
				type	= "color",
				},
			mainpos = {
				name	= L["Main name position"],
				desc	= L["Where to display a character's main name when on their alt."],
				type	= "text",
				order	= 100,
				get	= function() return self.db.profile.mainpos end,
				set	= function(v) self:setMainPos(v) end,
				validate = {
					["LEFT"]	= L["Left"],
					["RIGHT"]	= L["Right"],
	 				["START"]	= L["Start"],
					},
				},
			}
		}

	-- so it's possible to use "/alt add" or "/alt link"
	-- shows up twice in the FuBar list if set; commenting out for now
	--self.moduleOptions.args.add = self.moduleOptions.args.link

	return self.moduleOptions
end

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

-- things to do when the module is enabled
function Prat_AltNames:OnModuleEnable()
	-- things to do when the module is enabled
	for altname, mainname in pairs(self.db.profile.alts) do
		self.Alts[altname] = mainname
	end

	-- just register one area which can be used for anything
	-- (and only actually has one use at the moment)
	self.ALTNAMES = ""

	-- set
	self:setMainPos(self.db.profile.mainpos)


	-- register events
	self:RegisterEvent("Prat_PreAddMessage")

	local slashcmds = {
		'/altnames',
		'/alts',
		'/alt',
		}

	Prat:RegisterChatCommand(slashcmds, self.moduleOptions, string.upper(self.moduleName))
end

-- things to do when the module is disabled
function Prat_AltNames:OnModuleDisable()
	-- unregister events
	self:UnregisterAllEvents()
end


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

-- things do stuff here

function Prat_AltNames:formatMainName(mainname)
	--[[
	TODO
	format the main name as per the user's preferences (colour, bracket style)
	]]
end

function Prat_AltNames:print(msg, printanyway)
	printanyway = printanyway or ""

	-- make sure we've got a message
	if msg == nil then
		printanyway = true
		msg = 'ERROR: some function sent a blank message!'
	end

	if printanyway or not self.db.profile.quiet then
		msg = string.format("Alts: %s", msg)

		-- display it!
		DEFAULT_CHAT_FRAME:AddMessage(msg)
	end
end

function Prat_AltNames:formatCharName(name)
	-- format character names as having uppercase first letter followed by all lowercase

	if name == nil then
		return ""
	end

	name	= name:gsub('[%%%[%]":|%s]', '')
	name	= name:gsub("'", '')

	name	= string.lower(name)
	name	= string.gsub(name, "^(%w)", string.upper, 1)

	return name
end

function Prat_AltNames:addAlt(argstring)
	local altname, mainname
	local args = {}

	if argstring == nil then
		return false
	end

	for word in string.gmatch(argstring, "%S+") do table.insert(args, word) end

	if (table.getn(args) == 0) then
		return false
	elseif (table.getn(args) == 1) then
		self:print(string.format("No main name supplied to link %s to", args[1]), true)
		return false
	end

	altname, mainname = args[1], args[2]

	altname = self:formatCharName(altname)

	self.Alts[altname] = mainname
	self.db.profile.alts[altname] = mainname

	self:print(string.format("linked alt %s => %s", altname, mainname))
end


function Prat_AltNames:delAlt(altname)
	local suppliedaltname = altname

	altname = self:formatCharName(altname)

	if self.Alts[altname] then
		self.Alts[altname]		= nil
		self.db.profile.alts[altname]	= nil

		self:print(string.format("character removed: %s", suppliedaltname))

		return true
	end

	self:print(string.format('no characters called "%s" found; nothing deleted', suppliedaltname))
end

function Prat_AltNames:listAll()
	if not self.db.profile.alts and self.Alts then
		self:print(L["You have not yet linked any alts with their mains."], true)
		return false
	end

	local altcount = 0

	for altname, mainname in pairs(self.Alts) do
		altcount = altcount + 1
		self:print(string.format("%s => %s", altname, mainname))
	end

	self:print(string.format('%s total alts linked to mains', altcount))
end

function Prat_AltNames:findChars(q)
	local numfound

	local matchhighlight

	if not self.Alts then
		self:print(L["You have not yet linked any alts with their mains."], true)
		return false
	else
		local matches = {}
		local numfound = 0

		for altname, mainname in pairs(self.Alts) do
			local a = string.lower(altname)
			local m = string.lower(mainname)
			local pat = string.lower(q)

			-- self:print(string.format("matching against: altname:'%s', mainname:'%s', pat:'%s'", a, m, pat))

			if (a == pat) or (m == pat) or (a:find(pat)) or (m:find(pat)) then
				matches[altname] = mainname
				numfound = numfound + 1
			end
		end

		if numfound == 0 then
			self:print(string.format("no alts or mains found matching %s", q), true)
		else
			self:print(string.format("searched for: %s - found: %s", q, numfound))

			for altname, mainname in pairs(matches) do
				self:print(string.format("%s => %s", altname, mainname))
			end
		end

		return numfound
	end
end

function Prat_AltNames:importFromLOK()
	if not LOKWhoIsWho_Config then
		self:print('LOKWhoIsWho lua file not found, sorry.')
		return false
	end

	local server	= GetRealmName()
	local lokalts	= LOKWhoIsWho_Config[server]['players']

	if lokalts == nil then
		self:print("LOKWhoIsWho data not found")
		return false
	end

	local numimported = 0

	for altname, mainname in pairs(lokalts) do
		self:addAlt(string.format("%s %s", altname, mainname))

		numimported = numimported + 1
	end

	self:print(string.format("%s alts imported from LOKWhoIsWho", numimported))
end

function Prat_AltNames:fixAlts()
	local fixedalts = {}

	for altname, mainname in pairs(self.db.profile.alts) do
		altname		= self:formatCharName(altname)
		mainname	= self:formatCharName(mainname)

		fixedalts[altname] = mainname
	end

	self.Alts = fixedalts
	self.db.profile.alts = fixedalts
end


function Prat_AltNames:clearAllAlts()
	self.Alts		= {}
	self.db.profile.alts	= {}
end

function Prat_AltNames:setMainPos(pos)
	-- which item to go after, depending on our position
	local msgitems = {
		RIGHT	= 'Pp',
		LEFT	= 'Ff',
		START	= nil,
		}

	pos	= pos or 'RIGHT'

	Prat:RegisterMessageItem('ALTNAMES', msgitems[pos])

	if pos == 'RIGHT' then
		self.padfmt	= ' (%s)'
	else
		self.padfmt	= '(%s) '
	end

	self.db.profile.mainpos	= pos
end

function Prat_AltNames:Prat_PreAddMessage(message, frame)
	local mainname = message.PLAYERLINK

	if self.db.profile.on and self.Alts[mainname] then
		local altname	= self.Alts[mainname]
		local padfmt	= self.padfmt or ' (%s)'


		self.ALTNAMES	= string.format(padfmt, altname)

		if self.db.profile.colour then
			hexcolour	= CLR:GetHexColor(self.db.profile.colour)
			self.ALTNAMES	= '|cff' .. hexcolour .. self.ALTNAMES .. '|r'
		end

		message.ALTNAMES	= self.ALTNAMES
	end
end

function Prat_AltNames:getColour(r, g, b, a)
	local col = self.db.profile.colour
	if not col then return false end
	return col.r, col.g, col.b, nil
end
