---------------------------------------------------------------------------------
--
-- 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: PratSubstitutions
Revision: $Revision: 44429 $
Author(s): Sylvanaar
Website: http://files.wowace.com/Prat/
Documentation: http://www.wowace.com/wiki/Prat/Integrated_Modules#Substitutions
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
Based on: CFE2 by Satrina. (http://www.wowinterface.com/downloads/info6885-ChatFrameExtender2.html
Dependencies: Prat
Description: A module to provide basic chat substitutions. (default=off).
]]

-- Get Utility Libraries
local util, DBG, CLR = GetPratUtils()

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

if PRAT_MODULE == nil then
	return
end

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

L:RegisterTranslations("enUS", function() return {
	["Substitutions"] = true,
	["A module to provide basic chat substitutions."] = true,
	['substitution name'] = true,
	['substitution value'] = true,
	['add a substition'] = true,
} end)

--[[
	Chinese Local : CWDG Translation Team 昏睡墨鱼 (Thomas Mo)
	CWDG site: http://Cwowaddon.com
	$Rev: 44429 $
	$Date: 2007-07-21 15:41:41 +0200 (Sat, 21 Jul 2007) $
]]

L:RegisterTranslations("zhCN", function() return {
    ["Substitutions"] = "替换词语",
    ["A module to provide basic chat substitutions."] = "提供基本的替换聊天词语功能.",
} end)

L:RegisterTranslations("zhTW", function() return {
    ["Substitutions"] = "語詞替換",
    ["A module to provide basic chat substitutions."] = "提供基本的聊天語詞替換",
} end)

L:RegisterTranslations("deDE", function() return {
    ["Substitutions"] = "Ersetzungen",
    ["A module to provide basic chat substitutions."] = "Ein Modul, um grundlegende Chat-Ersetzungen zur Verf\195\188gung zu stellen.",
} end)

L:RegisterTranslations("koKR", function() return {
    ["Substitutions"] = "대체",
    ["A module to provide basic chat substitutions."] = "기본 대화 대체를 제공하는 모듈입니다.",
} end)

L:RegisterTranslations("esES", function() return {
    ["Substitutions"] = "Sustituciones",
    ["A module to provide basic chat substitutions."] = "Un módulo que provee sustituciones de chat básicas.",
} end)

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

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

-- define key module values
Prat_Substitutions.moduleName = L["Substitutions"]
Prat_Substitutions.moduleDesc = L["A module to provide basic chat substitutions."]

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

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

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

-- default values for any settings that need them
Prat_Substitutions.defaultDB = {
	on		= false,
	usersubs	= {},
	}

-- any boolean options
Prat_Substitutions.toggleOptions	= {}
Prat_Substitutions.usersubs_idx		= {}
Prat_Substitutions.modulePatterns	= {}

local usersub		= function(subname) return Prat_Substitutions:userSub(subname) end
local util, DBG, CLR = GetPratUtils()

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

local clrsubname = function(subname)
	subname = subname or ''

	return '|cff78ff64' .. subname .. '|r'
end

local clrexpansion = function(expandsto)
	expandsto = expandsto or ''

	return '|cff8ca0ff' .. expandsto .. '|r'
end

local fmtsubname = function(subname)
	if not subname then return false end

	subname = '%' .. subname

	return clrsubname(subname)
end


-- things to do when the module is enabled
function Prat_Substitutions:OnModuleEnable()
	self:BuildModuleOptions()
end


-- add module options not covered by templates
function Prat_Substitutions:GetModuleOptions()
	self.moduleOptions = {
		name	= self.moduleName,
		desc	= self.moduleDesc,
		type	= 'group',
		hidden	= function() self:BuildModuleOptions() end,


		args = {
			--[[ section including options for managing user defined substitutions ]]--
			USERDEFHEADER = { type = 'header',
				name	= 'User defined substitutions',
				desc	= 'Options for setting and removing user defined substitutions. (NB: users may define custom values for existing substitutions, but they will revert to the default value if the user definition is deleted.)',
				order	= 100,
				},

			--[[ substitution management ]]
			setsub = {
				name	= 'Set substitution',
				desc	= 'Set the value of a user defined substitution (NB: this may be the same as an existing default substitution; to reset it to the default, just remove the user created definition).',
				usage	= 'subname = text after expansion -- NOTE: sub name without the prefix "%"',
				order	= 110,
				type	= 'text',
				get	= false,
				set	= function(v)
						local name, value = self:splitArgs(v)
						return self:setSub(name, value)
					end
				},

			listsubs = {
				name	= 'List substitutions',
				desc	= 'Lists all current subtitutions in the default chat frame',
				type	= 'execute',
				order	= 120,
				func	= function() return self:listSubs() end,
				},


			delsub = {
				name	= 'Delete substitution',
				desc	= 'Deletes a user defined substitution',
				usage	= 'subname -- NOTE: sub name without the prefix \'%\'',
				order	= 130,
				type	= 'text',
				set	= function(v) return self:delSub(v) end,
				get	= false,
				confirm	= 'Are you sure?',
				},


			--[[
			delall = {
				name	= 'Delete all',
				desc	= 'Deletes all user defined substitutions',
				type	= 'execute',
				order	= 140,
				func	= function() return self:delAllSubs() end,
				confirm	= 'Are you sure - this will delete all user defined substitutions and reset defaults?',
				},
			]]


			--[[ blank line before header ]]--
			blankline = { type = 'header', order = 499 },

			--[[ lists subs below ]]--
			LISTHEADER = { type = 'header',
				name	= 'List of available substitutions',
				desc	= 'List of available substitutions defined by this module. (NB: users may define custom values for existing substitutions, but they will revert to the default value if the user definition is deleted.)',
				order	= 500,
				}

			-- NB: subs list build in the BuildModuleOptions() function, below
			},
	}

	return self.moduleOptions
end


function Prat_Substitutions:BuildModuleOptions()
	self.modulePatterns	= self:getInitialModulePatterns()
	self:addUserSubs()

	local args	= self.moduleOptions.args
	local order	= 500				-- starting val
	local usersubs	= Prat_Substitutions.db.profile.usersubs

	self.buildingMenu = true

	-- process standard module subtitutions
	for k,v in pairs(self.modulePatterns) do
		-- self:print('k, v.pattern: ' .. k .. ' + ' .. v.pattern)
		local name	= v.optname
		local pat	= string.gsub(v.pattern, "%%%%", "%%")

		order	= order + 10

		args[name] = args[name] or {}
		local d = args[name]

		d.name = name.." "..pat

		local matchfuncval = ""

		if v.matchfunc then
			matchfuncval = v.matchfunc() or ""
		else
			matchfuncval = "NO MATCHFUNC FOUND"
		end

		d.desc	= "Current value: '".. matchfuncval .."'\nClick to paste into the chat."
		d.type	= "execute"
		d.func	= function() self:DoPat(pat) end
		d.order	= order
	end

	-- all done
	self.buildingMenu = false
end



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





function Prat_Substitutions:splitArgs(str)
	-- make sure str is set, and not empty
	if (not str) or (str == '') then return false end

	-- str should be "<command>[=value| value]"
	local name, value

	-- should only match (word) (space or assignment operator) (value)
	for k, v in str:gmatch("%%?(%w+)%s*[%s=]%s*(.-)$") do
		name	= string.lower(k)
		value	= v or ''

		-- self:print('name ' .. name)
		-- self:print('value ' .. value)
	end

	return name, value
end


function Prat_Substitutions:print(msg)
	local colour	= 'ad66ff'

	msg = msg:gsub('[Ss]ubstitutions:%s*', '')

	util:print('|cff' .. colour .. 'Substitutions:|r ' .. msg)
end



-- :cleanStr - always returns at least a blank string

--	if passed a nil string, returns ""
--	takes a string an trims it, removes dodgy characters, and returns it

function Prat_Substitutions:cleanStr(str)
	if (not str) or (str == '') then return "" end

	str	= strtrim(str)
	--str	= str:gsub("[%w^a-z0-9'%\"_.- ]", '')
	str	= str:gsub('[%z%c|]', '')

	return str
end


local pattable = {}

function Prat_Substitutions:setSub(subname, expandsto)
	if not subname then return false end

	expandsto	= expandsto or ''

	subname		= self:cleanStr(subname)
	expandsto	= self:cleanStr(expandsto)

	if subname == '' then
		self:print('no substitution name given')
		return false
	end

	if expandsto == '' then
		self:print(string.format('no value given for subtitution "%s"', fmtsubname(subname)))
		return false
	end

	local usersubs	= self.db.profile.usersubs
	local existing	= usersubs[subname]

	if existing then
		self:print(string.format('|cffff0000warning:|r subtitution "%s" already defined as "%s", overwriting', fmtsubname(subname), clrexpansion(existing)))
	end

	-- { pattern = "(%%tn)", matchfunc=TargetName, optname="TargetName", type = "OUTBOUND"},

	local totalsubs = #Prat_Substitutions.modulePatterns
	local idx	= totalsubs + 1

	pattable	= self:patternTable(subname, expandsto)

	-- tell user we have a new sub of subname -> expandsto
	table.insert(Prat_Substitutions.modulePatterns, pattable)

	self:print('defined ' .. fmtsubname(subname) .. ': expands to => ' .. clrexpansion(expandsto))
	self.db.profile.usersubs[subname] = expandsto

	self:BuildModuleOptions()
	self:buildUserSubsIndex()
end


-- function to return a table suitable for inserting into Prat_Substitutions.modulePatterns
function Prat_Substitutions:patternTable(subname, expandsto)
	if not subname and expandsto then return false end


	--[[
	local pattern = {
		pattern = '(%%'..subname..')',
		matchfunc=function() return Prat_Substitutions:userSub(subname) end,
		optname='usersub_'..subname,
		type='OUTBOUND'
		}
	]]

	local pattern = {
		idx		= idx,
		pattern		= '(%%' .. subname .. ')',
		matchfunc	= function() return Prat_Substitutions:userSub(subname) end,
		optname		= 'usersub_' .. subname,
		type		= 'OUTBOUND',
		}

	return pattern
end


function Prat_Substitutions:delSub(subname)
	local usersubs		= self.db.profile.usersubs
	local subname		= self:cleanStr(subname)

	-- check shit
	if not subname or (subname == '') then
		self:print('no substitution name supplied for deletion')
		return false
	end

	if not usersubs then
		self:print('no user defined subs found')
		return false
	end

	if not usersubs[subname] then
		self:print(string.format('user defined substition "%s" not found', fmtsubname(subname)))
		return false
	end

	if (type(usersubs_idx) ~= 'table') then
		self:print("user substitutions index (usersubs_idx) doesn't exist! oh dear.")
		return false
	end

	local subidx		= usersubs_idx[subname]

	if not subidx then
		self:print(string.format("can't find substitution index for a substitution named '%s'", fmtsubname(subname)))
		return false
	end

	local expandsto	= usersubs[subname]

	self:print(string.format('removing user defined substitution "%s"; previously expanded to => ', fmtsubname, clrexpansion(expandsto)))

	self.modulePatterns[subidx]		= nil
	self.db.profile.usersubs[subname]	= nil
	self.usersubs_idx[subname]		= nil

	self:BuildModuleOptions()
	self:buildUserSubsIndex()
end

function Prat_Substitutions:delAllSubs()
	local usersubs = self.db.profile.usersubs

	if not (usersubs and subname) then return false end

	for subname, expandsto in pairs(usersubs) do
		self:delSub(subname)
	end

end


function Prat_Substitutions:listSubs()
	local usersubs = self.db.profile.usersubs

	if type(usersubs) ~= 'table' then
		self:print('no user defined subs found')
		return 51
	end

	local total = 0

	for subname, expandsto in pairs(usersubs) do
		self:print('substitution: ' .. fmtsubname(subname) .. ' defined as => ' .. clrexpansion(expandsto))

		total = total + 1
	end

	self:print(string.format('%d total user defined substitutions', total))
end


function Prat_Substitutions:userSub(subname)
	local usersubs	= self.db.profile.usersubs
	local expandsto

	if not usersubs then return false end

	expandsto	= usersubs[subname] or ""

	return expandsto
end

function  Prat_Substitutions:DoPat(pat)
	local e = ChatFrameEditBox
	if not e:IsVisible() then
		return
	end

	e:SetText((e:GetText() or "")..pat:gsub("[%(%)]", ""))
end

local function prat_match(text)
	local text = text or ""

	if Prat_Substitutions.buildingMenu then
		return text
	end

	return Prat:RegisterMatch(text, "OUTBOUND")
end

local function Zone(...)
	return prat_match(GetZoneText())
end

local function Loc(...)
	return prat_match(GetMinimapZoneText())
end

local function Pos()
	local x,y = GetPlayerMapPosition("player")
	local str = "("..math.floor((x * 100) + 0.5)..","..math.floor((y * 100) + 0.5)..")"
	return prat_match(str)
end

local function Ypos()
	local x, y = GetPlayerMapPosition("player")
	local y = tostring(math.floor((y * 100) + 0.5))
	return prat_match(y)
end

local function Xpos()
	local x, y = GetPlayerMapPosition("player")
	local x = tostring(math.floor((x * 100) + 0.5))
	return prat_match(x)
end

local function PlayerHP(...)
	return prat_match(UnitHealth("player"))
end

local function PlayerMaxHP(...)
	return prat_match(UnitHealthMax("player"))
end

local function PlayerPercentHP()
	return prat_match(floor(100 * (UnitHealth("player") / UnitHealthMax("player"))))
end

local function PlayerHealthDeficit()
	return prat_match(UnitHealthMax("player") - UnitHealth("player"))
end

local function PlayerCurrentMana()
	return prat_match(UnitMana("player"))
end

local function PlayerMaxMana()
	return prat_match(UnitManaMax("player"))
end

local function PlayerPercentMana()
	return prat_match(string.format("%.0f%%%%",
	floor(100 * (UnitMana("player")/UnitManaMax("player")))))
end

local function PlayerManaDeficit()
	return prat_match(UnitManaMax("player") - UnitMana("player"))
end



local function TargetPercentHP()
	local str = "<notarget>"
	if UnitExists("target") then
		str = string.format("%.0f%%%%", floor(100 * (UnitHealth("target") / UnitHealthMax("target"))))
	end

	return prat_match(str)
end

local function TargetHealth()
	local str = "<notarget>"
	if UnitExists("target") then
		str = UnitHealth("target")
	end

	return prat_match(str)
end

local function TargetHealthDeficit()
	local str = "<notarget>"
	if UnitExists("target") then
		str = UnitHealthMax("target") - UnitHealth("target")
	end

	return prat_match(str)
end

local function TargetManaDeficit()
	local str = "<notarget>"
	if UnitExists("target") then
		str = UnitManaMax("target") - UnitMana("target")
	end

	return prat_match(str)
end


local function TargetClass()
	local class = "<notarget>"
	if UnitExists("target") then
		class = UnitClass("target")
	end

	return prat_match(class)
end
local function TargetRace()
	local race = "<notarget>"
	if UnitExists("target") then
		if UnitIsPlayer("target") then
			race = UnitRace("target")
		else
			race = UnitCreatureFamily("target")
			if not race then
				race = UnitCreatureType("target")
			end
		end
	end
	return prat_match(race)
end
local function TargetGender()
	local sex = "<notarget>"
	if UnitExists("target") then
		s = UnitSex("target")
		if(s == 2) then
			sex = "male"
		elseif (s == 3) then
			sex = "female"
		else
			sex = "unknown sex"
		end
	end

	return prat_match(sex)
end

local function TargetLevel()
	local level = "<notarget>"
	if UnitExists("target") then
		level = UnitLevel("target")
	end
	return prat_match(level)
end

local function TargetGuild()
	local guild = "<notarget>"
	if UnitExists("target") then
		guild = "<noguild>"
		if IsInGuild("target") then
			guild = GetGuildInfo("target") or ""
		end
	end
	return prat_match(guild)
end

-- %tps (possesive)
local function TargetPossesive()
	local p = "<notarget>"
	if UnitExists("target") then
		local s = UnitSex("target")
		if(s == 2) then
			p = "his"
		elseif (s == 3) then
			p = "hers"
		else
			p = "its"
		end
	end

	return prat_match(p)
end

-- %tpn (pronoun)
local function TargetPronoun()
	local p = "<notarget>"
	if UnitExists("target") then
		local s = UnitSex("target")
		if(s == 2) then
			p = "him"
		elseif (s == 3) then
			p = "her"
		else
			p = "it"
		end
	end
	return prat_match(p)
end

-- %tn (target)
local function TargetName()
	local t = '<notarget>'

	if UnitExists("target") then
		t = UnitName("target")
	end

	return prat_match(t)
end

-- %tt (target)
local function TargetTargetName()
	local t = '<notarget>'

	if UnitExists("targettarget") then
		t = UnitName("targettarget")
	end

	return prat_match(t)
end

-- %pn (player)
local function PlayerName()
	local p = GetUnitName("player") or ""
	return prat_match(p)
end

local function Rand()
	return math.random(1, 100)
end

--[[
* %tn = current target
* %pn = player name
* %hc = your current health
* %hm = your max health
* %hp = your percentage health
* %hd = your current health deficit
* %mc = your current mana
* %mm = your max mana
* %mp = your percentage mana
* %md = your current mana deficit
* %thp = target's percentage health
* %th = target's current health
* %td = target's health deficit
* %tc = class of target
* %tr = race of target
* %ts = sex of target
* %tl = level of target
* %tps = possesive for target (his/hers/its)
* %tpn = pronoun for target (him/her/it)
* %fhp = focus's percentage health
* %fc = class of focus
* %fr = race of focus
* %fs = sex of focus
* %fl = level of focus
* %fps = possesive for focus (his/hers/its)
* %fpn = pronoun for focus (him/her/it)
* %tt = target of target
* %zon = your current zone (Dun Morogh, Hellfire Peninsula, etc.)
* %loc = your current subzone (as shown on the minimap)
* %pos = your current coordinates (x,y)
* %ypos = your current y coordinate
* %xpos = your current x coordinate
* %rnd = a random number between 1 and 100
--]]

function Prat_Substitutions:getInitialModulePatterns()
	local modulePatterns = {
		{ pattern = "(%%thd)", matchfunc=TargetHealthDeficit, optname="TargetHealthDeficit", type = "OUTBOUND"},
		{ pattern = "(%%thp)", matchfunc=TargetPercentHP, optname="TargetPercentHP",  type = "OUTBOUND"},
		{ pattern = "(%%tpn)", matchfunc=TargetPronoun, optname="TargetPronoun",  type = "OUTBOUND"},

		{ pattern = "(%%hc)", matchfunc=PlayerHP, optname="PlayerHP",  type = "OUTBOUND"},
		{ pattern = "(%%pn)", matchfunc=PlayerName, optname="PlayerName", type = "OUTBOUND"},
		{ pattern = "(%%hm)", matchfunc=PlayerMaxHP, optname="PlayerMaxHP",  type = "OUTBOUND"},
		{ pattern = "(%%hd)", matchfunc=PlayerHealthDeficit, optname="PlayerHealthDeficit", type = "OUTBOUND"},
		{ pattern = "(%%hp)", matchfunc=PlayerPercentHP, optname="PlayerPercentHP",  type = "OUTBOUND"},
		{ pattern = "(%%mc)", matchfunc=PlayerCurrentMana, optname="PlayerCurrentMana",  type = "OUTBOUND"},
		{ pattern = "(%%mm)", matchfunc=PlayerMaxMana, optname="PlayerMaxMana",  type = "OUTBOUND"},
		{ pattern = "(%%mp)", matchfunc=PlayerPercentMana, optname="PlayerPercentMana",  type = "OUTBOUND"},
		{ pattern = "(%%pmd)", matchfunc=PlayerManaDeficit, optname="PlayerManaDeficit", type = "OUTBOUND"},

		{ pattern = "(%%tn)", matchfunc=TargetName, optname="TargetName", type = "OUTBOUND"},
		{ pattern = "(%%tt)", matchfunc=TargetTargetName, optname="TargetTargetName", type = "OUTBOUND"},
		{ pattern = "(%%tc)", matchfunc=TargetClass, optname="TargetClass", type = "OUTBOUND"},
		{ pattern = "(%%th)", matchfunc=TargetHealth, optname="TargetHealth", type = "OUTBOUND"},
		{ pattern = "(%%tr)", matchfunc=TargetRace, optname="TargetRace",  type = "OUTBOUND"},
		{ pattern = "(%%ts)", matchfunc=TargetGender, optname="TargetGender",  type = "OUTBOUND"},
		{ pattern = "(%%tl)", matchfunc=TargetLevel, optname="TargetLevel",  type = "OUTBOUND"},
		{ pattern = "(%%tps)", matchfunc=TargetPossesive, optname="TargetPossesive",  type = "OUTBOUND"},
		{ pattern = "(%%tmd)", matchfunc=TargetManaDeficit, optname="TargetManaDeficit", type = "OUTBOUND"},
		{ pattern = "(%%tg)", matchfunc=TargetGuild, optname="TargetGuild", type = "OUTBOUND"},


		{ pattern = "(%%zon)", matchfunc=Zone, optname="MapZone",  type = "OUTBOUND"},
		{ pattern = "(%%loc)", matchfunc=Loc, optname="MapLoc",  type = "OUTBOUND"},
		{ pattern = "(%%pos)", matchfunc=Pos, optname="MapPos",  type = "OUTBOUND"},
		{ pattern = "(%%ypos)", matchfunc=Ypos, optname="MapYPos",  type = "OUTBOUND"},
		{ pattern = "(%%xpos)", matchfunc=Xpos, optname="MapXPos",  type = "OUTBOUND"},
		{ pattern = "(%%rnd)", matchfunc=Rand, optname="RandNum", type = "OUTBOUND"},

		--~	 { pattern = "(%%tn)", matchfunc=TargetName, optname="Target", type = "OUTBOUND"},
		--~	 { pattern = "(%%pn)", matchfunc=PlayerName, optname="Player", type = "OUTBOUND"}
		}

		--[[ TODO:
		%%fhp - focus health
		%%fr
		%%fc
		%%fs
		%%fl
		%%fvr
		%%fvn
		]]

	return modulePatterns
end

function Prat_Substitutions:userSubIdx(subname)
	if not subname then return false end

	local usersubs_idx	= self.usersubs_idx or {}

	if usersubs_idx[subname] then
		return usersubs_idx[subname]
	end

	local tmpsubname

	for idx, pattern in Prat_Substitutions.modulePatterns do
		tmpsubname = pattern.optname:gsub('^user_', '')

		if usersubs[tmpsubname] then
			usersubs_idx[tmpsubname] = idx

			return idx
		end
	end

	return false
end


function Prat_Substitutions:addUserSubs()
	self.usersubs_idx = {}

	for subname, expandsto in pairs(self.db.profile.usersubs) do
		local pattable = self:patternTable(subname, expandsto)

		table.insert(self.modulePatterns, pattable)

		self.usersubs_idx = pattable.idx
	end
end

function Prat_Substitutions:buildUserSubsIndex()
	local usersubs		= self.db.profile.usersubs
	local modpats		= self.modulePatterns

	self.usersubs_idx = {}

	if not modpats then
		self:print('Prat_Substitutions:buildUserSubsIndex(): warning: module patterns not defined!')
		return false
	end

	for idx, pattern in ipairs(modpats) do
		local subname = pattern.optname:gsub('^user_', '')

		if usersubs[subname] then
			usersubs_idx[subname]				= idx
			Prat_Substitutions.usersubs_idx[subname]	= idx
		end
	end

	return usersubs_idx
end
