
local me = { name = "combatparser"}
local mod = thismod
mod[me.name] = me

--[[
CombatParser.lua

This module is the bridge between Regex.lua and Combat.lua. Given a combat log event, it feeds it to the parser.
If successful, the parser will return a set of arguments, and an identifier that describes the combat log line, such as "whiteattackhit".

CombatParser then works out what to do with the arguments. That is, it massages them into a format for Combat.lua's methods.

]]

me.myparsers = 
{
	-- in 2.0, damage from Hunter's Autoshot and Wands is counted as "Your Hits"
	{"autoattack", "COMBATHITSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, 		-- "You hit %s for %d."
	{"autoattack", "COMBATHITCRITSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, -- "You crit %s for %d."
	{"autospecial", "SPELLLOGSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, 			-- "Your %s hits %s for %d."
	{"autospecial", "SPELLLOGCRITSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, 	-- "Your %s crits %s for %d."
	{"autospecial", "SPELLLOGSCHOOLSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, 			-- "Your %s hits %s for %d %s damage."
	{"autospecial", "SPELLLOGCRITSCHOOLSELFOTHER", "CHAT_MSG_COMBAT_SELF_HITS"}, 	-- "Your %s crits %s for %d %s damage."
	
	{"damageshield", "DAMAGESHIELDSELFOTHER", "CHAT_MSG_SPELL_DAMAGESHIELDS_ON_SELF"}, -- "You reflect %d %s damage to %s."
	
	{"abilityhit", "SPELLLOGSELFOTHER", "CHAT_MSG_SPELL_SELF_DAMAGE"}, 			-- "Your %s hits %s for %d."
	{"abilitycrit", "SPELLLOGCRITSELFOTHER", "CHAT_MSG_SPELL_SELF_DAMAGE"}, 	-- "Your %s crits %s for %d."

	{"spellcrit", "SPELLLOGCRITSCHOOLSELFOTHER", "CHAT_MSG_SPELL_SELF_DAMAGE"}, -- "Your %s crits %s for %d %s damage."
	{"spellhit", "SPELLLOGSCHOOLSELFOTHER", "CHAT_MSG_SPELL_SELF_DAMAGE"},		-- "Your %s hits %s for %d %s damage."
	{"perform", "SPELLPERFORMGOSELFTARGETTED", "CHAT_MSG_SPELL_SELF_DAMAGE"}, 	-- "You perform %s on %s."
	{"spellcast", "SPELLCASTGOSELFTARGETTED", "CHAT_MSG_SPELL_SELF_DAMAGE"},	-- "You cast %s on %s."
	
  {"othersdotonother", "PERIODICAURADAMAGEOTHEROTHER", "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE"}, -- added for korean
	{"dot", "PERIODICAURADAMAGESELFOTHER", "CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE"}, -- "%s suffers %d %s damage from your %s."
	
  
	{"othershotonother", "PERIODICAURAHEALOTHEROTHER", "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS"}, -- "%s gains %d health from %s' %s."
	{"yourhotonother", "PERIODICAURAHEALSELFOTHER", "CHAT_MSG_SPELL_PERIODIC_FRIENDLYPLAYER_BUFFS"}, -- "%s gains %d health from your %s."
  
	{"othershotonother", "PERIODICAURAHEALOTHEROTHER", "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS"}, -- "%s gains %d health from %s' %s."
	{"yourhotonother", "PERIODICAURAHEALSELFOTHER", "CHAT_MSG_SPELL_PERIODIC_PARTY_BUFFS"}, -- "%s gains %d health from your %s."
  
	{"othershotonyou", "PERIODICAURAHEALOTHERSELF", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, -- "You gain %d health from %s's %s."
	{"othershotonother", "PERIODICAURAHEALOTHEROTHER", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, -- "You gain %d health from %s's %s."
	{"yourhotonother", "PERIODICAURAHEALSELFOTHER", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"}, -- "%s gains %d health from your %s."

	{"hotonself", "PERIODICAURAHEALSELFSELF", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},-- "You gain %d health from %s."
	{"powergain", "POWERGAINSELFSELF", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},		-- "You gain %d %s from %s."
	{"powergainfromother", "POWERGAINSELFOTHER", "CHAT_MSG_SPELL_PERIODIC_SELF_BUFFS"},		-- "You gain %d %s from %s's %s."
	
	{"healonother", "HEALEDSELFOTHER", "CHAT_MSG_SPELL_SELF_BUFF"},			-- "Your %s heals %s for %d."
	{"healonother", "HEALEDCRITSELFOTHER", "CHAT_MSG_SPELL_SELF_BUFF"},		-- "Your %s critically heals %s for %d."	
	{"healonself", "HEALEDSELFSELF", "CHAT_MSG_SPELL_SELF_BUFF"},			-- "Your %s heals you for %d."
	{"healonself", "HEALEDCRITSELFSELF", "CHAT_MSG_SPELL_SELF_BUFF"},		-- "Your %s critically heals you for %d."
	{"powergain", "POWERGAINSELFSELF", "CHAT_MSG_SPELL_SELF_BUFF"},			-- "You gain %d %s from %s."
}

me.onparse = function(identifier, ...)

-- simple debug
msg = identifier .. ": "

for x = 1, select("#", ...) do
	msg = msg .. select(x, ...) .. ", "
end

-- mod.print(msg)



	-- Reset combat args
	me.action.type = ""
	me.action.spellname = ""
	me.action.spellid = ""
	me.action.damage = 0
	me.action.target = ""
	me.action.iscrit = false
	me.action.isdot = false
	me.action.spellschool = ""
	
	-- check a stage two handler is defined
	if me.parserstagetwo[identifier] == nil then
		if mod.trace.check("error", me, "parser") then
			mod.trace.print(string.format("No handler is defined for a %s parse!", identifier))
		end
		
		return
	end
	
	-- run the stage two handler
	me.parserstagetwo[identifier](...)

   -- check a stage 3 handler is defined
   if me.parserstagethree[me.action.type] == nil then
		if mod.trace.check("error", me, "parser") then   
			mod.trace.print(string.format("No stage handler is defined for a %s action!", me.action.type))
		end
		return
	end
	
   -- run the stage 3 handler
   me.parserstagethree[me.action.type]()
   
end

--[[
type can be:

attack			anything that causes damage
heal				any source of healing from you
powergain		you gain x rage / mana / energy
nothing			actions that don't change threat
special			non-damaging abilities, e.g. taunt / feint

]]

me.action = 
{
	type = "",
	spellname = "",
	spellid = "",
	damage = 0,
	target = "",
	iscrit = false,
	isdot = false,
	spellschool = "",
}

--[[
Combining some parsers is possible. e.g. autoattack hits and crits can go together. Even if in one locale they look completely different, or have different orderings, once they go through stage one they will come out the same. And for an autoattack we don't care whether it's a crit or not (only for abilities, to calculate the rage cost of heroic strike or maul more accurately).
]]
me.parserstagetwo = 
{
	["autoattack"] = function(target, damage)
		me.action.spellid = "whitedamage"
		me.action.damage = damage
		me.action.target = target
		me.action.type = "attack"
      
	end,
	
	["autospecial"] = function(ability, target, damage)
		me.action.spellid = "whitedamage"
		me.action.damage = damage
		me.action.target = target
		me.action.type = "attack"
      
	end,
	
	["damageshield"] = function(damage, school, target)
		me.action.damage = damage
		me.action.target = target
		me.action.spellschool = school
    	me.action.type = "attack"
		me.action.spellid = "damageshield"
		
	end,
	
	["abilityhit"] = function(name, target, damage)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
	   me.action.type = "attack"
      
	end,
	
	["abilitycrit"] = function(name, target, damage)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
		me.action.iscrit = true
		me.action.type = "attack"
      
	end,
	
	["spellhit"] = function(name, target, damage, school)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
		me.action.spellschool = school
		me.action.type = "attack"
      
	end,
	
	["spellcrit"] = function(name, target, damage, school)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
		me.action.spellschool = school
		me.action.iscrit = true
		me.action.type = "attack"
      
	end,
	
	["perform"] = function(name, target)
		me.action.spellname = name
		me.action.target = target
		me.action.type = "special"
      
	end,
	
	["spellcast"] = function(name, target)
		me.action.spellname = name
		me.action.target = target
		me.action.type = "special"
      
	end,

	["othersdotonother"] = function()
    	me.action.type = "nothing"
		
	end,

	["dot"] = function(target, damage, school, name)
		me.action.spellname = name
		me.action.isdot = "true"
		me.action.damage = damage
		me.action.target = target
		me.action.spellschool = school
		me.action.type = "attack"
      
	end,
	
	["yourhotonother"] = function(target, damage, name)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
		me.action.type = "heal"
      
	end,
	
	-- check that we don't do anything when we get this
	["othershotonyou"] = function()
	   me.action.type = "nothing"
      
	end,
	
	["othershotonother"] = function()
	   me.action.type = "nothing"
      
	end,
	
	-- healing on self. Leave target = nil
	["hotonself"] = function(damage, name)
		me.action.spellname = name
		me.action.damage = damage
		me.action.type = "heal"
      
	end,
	
	-- this filters out Mana tide Totem / Blessing of Wisdom
	["powergainfromother"] = function()
		me.action.type = "nothing"
	end,
	
	-- powertype is put in the target section
	["powergain"] = function(damage, powertype, name)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = powertype
				
		me.action.type = "powergain"
      
	end,
	
	["healonself"] = function(name, damage)
		me.action.spellname = name
		me.action.damage = damage
		me.action.type = "heal"
      
	end,
	
	["healonother"] = function(name, target, damage)
		me.action.spellname = name
		me.action.damage = damage
		me.action.target = target
		me.action.type = "heal"
      
	end,
	
}

me.parserstagethree = 
{
   ["attack"] = function()
		
		-- find the ID of special abilities
		if me.action.spellid == "" then
			me.action.spellid = mod.string.unlocalise("spell", me.action.spellname)
		end
		
		-- check for specials
		if me.action.spellid and mod.data.spells[me.action.spellid] then
			-- this is a potentially a special attack, check the class matches
			
			local class = mod.data.spells[me.action.spellid].class
			
			if class == "item" or class == mod.my.class then
				
				-- class matches. submit as special attack
				mod.combat.specialattack(me.action.spellid, me.action.target, me.action.damage, me.action.iscrit, me.action.spellschool, me.action.isdot)
				return
				
			end
		end
		
		-- not a special attack
		mod.combat.normalattack(me.action.spellname, me.action.spellid, me.action.damage, nil, me.action.target, me.action.iscrit, me.action.spellschool)
		
	end,
	
	["heal"] = function()
		if me.action.target == "" then
			me.action.target = UnitName("player")
		end
		
		-- check for a spellid
		me.action.spellid = mod.string.unlocalise("spell", me.action.spellname)
		
		mod.combat.possibleoverheal(me.action.spellname, me.action.spellid, me.action.damage, me.action.target)
		
	end,
	
	["nothing"] = function()
	
	end,
	
	["powergain"] = function()
		me.action.spellid = mod.string.unlocalise("spell", me.action.spellname)
		mod.combat.powergain(me.action.damage, me.action.target, me.action.spellid)
		
	end,
	
	["special"] = function()
		
		-- 1) Unlocalise the ability. e.g. "Heroic Strike" -> "heroicstrike", "Heldenhafter Sto\195\159" -> "heroicstrike"
		me.action.spellid = mod.string.unlocalise("spell", me.action.spellname)
		
		-- 2) Taunt / Growl
		if (me.action.spellid == "taunt") or (me.action.spellid == "growl") or (me.action.spellid == "righteousdefense") then
			mod.combat.taunt(me.action.target)
		
		elseif (me.action.spellid == "soulshatter") then
			mod.combat.soulshatter()
		
		-- 3) Special Abilities that don't cause damage, but have threat modifiers. e.g. Feint / Cower.
		elseif me.action.spellid and mod.data.spells[me.action.spellid] then
			mod.combat.specialattack(me.action.spellid, me.action.target, 0, nil, nil, nil)
			
		-- 4) Unrelated abilities
		else
			return
		end
		
	end,
	
}



