
-----------------------------------------------------------
-- LibAddonManager.lua
-----------------------------------------------------------
-- Take the global "..." (name, addon) as parameters to
-- initialize an addon object.
--
-- Abin (2014-11-04)

-----------------------------------------------------------
-- API Documentation:
-----------------------------------------------------------

-- addon = LibAddonManager:CreateAddon("name", addon) -- Take over the addon object

-- addon is a table represents your addon object, it contains the following field upon creation:

-- version: string, the value of fileld "## Version" in toc file, or "1.0" if missing
-- numericVersion: number, numeric form of version
-- name: string, name of the addon, same as the toc file name
-- title: string, same as "name" by default but developers may change for different locales
-- player: string, player name
-- realm: string, current realm name
-- faction: string, player faction group in English, either "Alliance" or "Horde"
-- class: string, player class in upper-cased English, "WARRIOR", "MAGE", "PALADIN" etc.
-- race: string, player race in English, "Human", "NightElf", "Troll", etc.
-- guid: string, GUID of the player

-- And the following functions & methods are defined for the object:

-- addon.tcopy(source [, destination]) -- Copy entire table data includes sub-tables from source to destination, return new table
-- addon.tfind(table, value) -- Seach a numeric based table for match value, return index
-- addon.tfind(table, func, ...) -- Seach a numeric based table for match value using defined function, return index, [boolean] func(element, ...)

-- addon:Print("text" [, r, g, b]) -- Prints a message
-- addon:Debug("text") -- Prints a message ONLY if addon.debug is true

-- addon:Initialized() -- Returns whether the addon has been initialized
-- addon:RegisterDB("dbName", hasCharDB) -- "hasCharDB" can be string, in which case char db will be the contents in toc field "SavedVariablesPerCharacter". Non-string type will treated as "name - realm" stored in db["profiles"]
-- addon:VerifyDBVersion(version [, db]) -- Returns true only if value of [db].version is numeric and no smaller than the specified version value
-- addon:RegisterSlashCmd("command1" [, "command2" [, ...]]) -- Register slash commands, no limited numbers
-- addon:RegisterBindingClick(button, "name", "text") -- Set an override binding click to a button, "name" is the binding name, "text" is what appears in the game's "Key Bindings" UI
-- addon:GetCurProfileName() -- Return current profile name string, in format of "name - realm"
-- addob:GetProfileNameList() -- Return a table stores list of profile names { "name1", "name2", ... }
-- addon:GetProfileData("name") -- Return the profile data table specified by "name"
-- addon:CopyProfile("src" [, "dest"]) -- Copy contents from profile "src" to "dest", copy to current profile if "dest" is not specified
-- addon:DeleteProfile("name") -- Delete a profile specified by "name", cannot delete current profile

-- addon:RegisterLocale("name", "locale", data) -- Register a localized string table
-- addon:GetLocale("name", "locale") -- Get a registered string table

-- addon:PopupShowConfirm("text", func, arg1 [, "buttons"]) -- Show a popup dialog without editbox, func(arg1) will be called. "buttons" can be "MB_OK", "MB_OKCANCEL", "MB_YESNO", "MB_ACCEPTCANCEL", "MB_ACCEPTDECLINE"
-- addon:PopupShowAck("text" [, func, arg1]) -- Show an acknowledgement dialog with a fixed "Okay" button
-- addon:PopupShowInput("text", func, arg1, "default" [, wide]) -- Show a popup dialog with editbox for user inputs, func(arg1, "text") will be called. editbox width will be set to 260 if "wide" is true
-- addon:PopupHide() -- Hide the popup dialog shown by this addon

-- addon:EmbedEventObject([ object ]) -- Embeds an object with event-handling capability
-- addon:RegisterEvent("event" [, func])
-- addon:RegisterEvent("event" [, "method"])
-- addon:UnregisterEvent("event")
-- addon:RegisterAllEvents()
-- addon:UnregisterAllEvents()
-- addon:RegisterTick(interval)
-- addon:UnregisterTick()
-- addon:SetInterval(interval)
-- addon:IsTicking()
-- addon:BroadcastEvent("event" [, ...])
-- addon:RegisterEventCallback("event", func [, arg1])
-- addon:BroadcastOptionEvent(option [, ...])
-- addon:RegisterOptionCallback("option", func [, arg1])

-- addon:CreateModule("key", "dbType" [, ...]) -- Create a module using an unique key, "dbType" can be "ACCOUNT", "CHAR" or "ACCOUNT|CHAR", ... can be anything
-- addon:NumModules() -- Return number of modules registered in this addon
-- addon:GetModule(index) -- Get a module specified by index
-- addon:GetModule("key") -- Get a module specified by key string
-- addon:EnumModules(func, ...) -- Enum all modules and call func(module, ...)
-- addon:CallAllModules("method", ...) -- Call all modules' method specified by "method"(STRING), regardless the enable/disable states of the module
-- addon:CallAllEnabledModules("method", ...) -- Call all modules' method specified by "method"(STRING), only enabled modules are involved

-----------------------------------------------------------
-- Callback functions:
-----------------------------------------------------------

-- addon:OnInitialize(db, dbIsNew, chardb, chardbIsNew) -- Called when PLAYER_LOGIN event fires
-- addon:OnModulesInitDone() -- Called after all modules of this addon are initialized done
-- addon:OnTick(elapsed) -- Fires when ticking
-- addon:OnSlashCmd(text) -- Fires when the user types a slash command registered by this addon
-- addon:OnVerifyModule("key", "dbType" [, ...]) -- Called before creates a new module, if this method exists and returns nil/false, the creatiopn fails
-- addon:OnCreateModule(module, "key", ...) -- Called when a new module is created, "..." is what passed in addon:CreateModule
-- addon:OnEvent(event, ...) -- Fires when an event fires and this callback is defined
-- addon:OnEnterCombat() -- Fires when the player enters combat
-- addon:OnLeaveCombat() -- Fires when the player leaves combat

-----------------------------------------------------------
-- Module functions:
-----------------------------------------------------------

-- module:Enable()
-- module:Disable()
-- module:IsEnabled()

-----------------------------------------------------------
-- Module callback functions:
-----------------------------------------------------------

-- module:OnInitialize(db, dbIsNew, chardb, chardbIsNew) -- Fires after the PLAYER_LOGIN event fires, db and chardb are subsets of the addon dbs
-- module:OnEnable() -- Fires when the module is enabled via "module:Enable()"
-- module:OnDisable() -- Fires when the module is disabled via "module:Disable()"
-- module:OnTick(elapsed) -- Fires when ticking
-- module:OnEvent(event, ...) -- Fires when an event fires and this callback is defined
-- module:OnEnterCombat() -- Fires when the player enters combat, only for enabled modules
-- module:OnLeaveCombat() -- Fires when the player leaves combat, only for enabled modules

-----------------------------------------------------------

local type = type
local CreateFrame = CreateFrame
local tinsert = tinsert
local GetAddOnMetadata = GetAddOnMetadata
local tonumber = tonumber
local tostring = tostring
local select = select
local strupper = strupper
local strfind = strfind
local strtrim = strtrim
local wipe = wipe
local ClearOverrideBindings = ClearOverrideBindings
local GetBindingKey = GetBindingKey
local SetOverrideBindingClick = SetOverrideBindingClick
local pairs = pairs
local ipairs = ipairs
local InCombatLockdown = InCombatLockdown
local UnitName = UnitName
local GetRealmName = GetRealmName
local UnitFactionGroup = UnitFactionGroup
local UnitClass = UnitClass
local UnitGUID = UnitGUID
local format = format
local error = error
local StaticPopup_Show = StaticPopup_Show
local StaticPopup_Hide = StaticPopup_Hide
local StaticPopupDialogs = StaticPopupDialogs
local _G = _G

local VERSION = 1.22

local lib = _G.LibAddonManager
if type(lib) == "table" then
	local version = lib.version
	if type(version) == "number" and version >= VERSION then
		return
	end
else
	lib = {}
	_G.LibAddonManager = lib
end

lib.version = VERSION

local PRIVATE = "{62B10A9A-6AF5-40EF-93F6-D7271489AA66}"

local PLAYER_INFO = {}
local PROFILE_NAME

-------------------------------------------------------
-- Library utility function
-------------------------------------------------------

function lib.tcopy(src, dest)
	if type(dest) == "table" then
		wipe(dest)
	else
		dest = {}
	end

	local k, v
	for k, v in pairs(src) do
		if type(v) == "table" then
			dest[k] = lib.tcopy(v)
		else
			dest[k] = v
		end
	end

	return dest
end

function lib.tfind(t, arg, ...)
	if type(t) ~= "table" then
