MI2_Target = {}
MI2_CurZone = 0
MI2_IsNonMobLoot = nil

local MI2_EventHandlers = { }
local MI2_GT_OnShow_Orig
local MI2_Scan_SelfBuff
local MI2_LootFrameOpen = false

local function MI2_CheckForSeparateMobHealth()
	if  MobHealth_OnLoad  then
		if  MobInfoConfig.DisableHealth ~= 2  then
			MobInfoConfig.DisableHealth = 2
			UIErrorsFrame:AddMessage( MI_TXT_MH_DISABLED, 0.0, 1.0, 1.0, 1.0, 20 )
		end
		MI2_MobHealthFrame:Hide()
	else
		if  MobInfoConfig.DisableHealth ~= 0  then
			MobInfoConfig.DisableHealth = 0
		end
	end
end

local function MI2_VariablesLoaded()
	MI2_InitOptions()
	MI2_RegisterWithAddonManagers()
	MI2_CheckForSeparateMobHealth()
	if  MobInfoConfig.DisableHealth < 2  then
		MI2_MobHealth_SetPos()
	end
	if  MobHealthFrame == "MI2"  then
		MobHealthFrame = MI2_MobHealthFrame
	end
	StaticPopupDialogs["MOBINFO_CONFIRMATION"] = {
		button1 = TEXT(OKAY),
		button2 = TEXT(CANCEL),
		showAlert = 1,
		timeout = 0,
		exclusive = 1,
		whileDead = 1,
		interruptCinematic = 1
	}
	StaticPopupDialogs["MOBINFO_SHOWMESSAGE"] = {
		button1 = TEXT(OKAY),
		showAlert = 1,
		timeout = 0,
		exclusive = 1,
		whileDead = 1,
		interruptCinematic = 1
	}
	local ver = MobInfoDB["DatabaseVersion:0"]
	if ver and ver.loc and ver.loc ~= GetLocale() then
		StaticPopupDialogs["MOBINFO_SHOWMESSAGE"].text = mifontRed..MI_TXT_WRONG_LOC
		local dialog = StaticPopup_Show( "MOBINFO_SHOWMESSAGE", "")
	end
	MI2_CleanupDatabases()
	MI2_SetPlayerName()
	MI2_UpdateMobInfoState()
	MI2_SlashInit()
	MI2_BuildXRefItemTable()
	MI2_InitializeEventTable()
	local newSchools = {}
	local school, schortcut
	for school, schortcut in pairs(MI2_SpellSchools) do
		newSchools[school] = schortcut
		newSchools[schortcut] = school
	end
	MI2_SpellSchools = newSchools
	MI2_GT_OnShow_Orig = GameTooltip:GetScript("OnShow")
	GameTooltip:SetScript( "OnShow", MI2_GameTooltip_OnShow )
end

local function MI2_EventLootOpened( )
	local mobIndex = MI2_Target.mobIndex or MI2_LastTargetIdx
	local numItems = GetNumLootItems()
	MI2_CurrentCorpseIndex = nil
	MI2_LootFrameOpen = true
	if (not MI2_Target.mobIndex and numItems > 0)
			or (MI2_Target.mobIndex and not UnitIsDead("target")) or MI2_IsNonMobLoot then
		MI2_IsNonMobLoot = false
		return
	end
		if not mobIndex and not ERR_NO_LOOT_TARGET_SHOWN then
		chattext( "MobInfo Warning: loot window opened without valid target" )
		ERR_NO_LOOT_TARGET_SHOWN = 1
		return
	end
	if MI2_CheckForCorpseReopen(mobIndex) then
		midebug( "corpse REOPEN detected", 1 )
		return
	end
	MI2_RecordAllLootItems( mobIndex, numItems )
end

local function MI2_EventLootSlotCleared( )
	MI2_StoreCorpseId( MI2_GetCorpseId(MI2_Target.mobIndex) )
end

local function MI2_EventLootClosed( )
	local mobIndex = MI2_Target.mobIndex
	if mobIndex and not MI2_LootFrameOpen then
		MI2_RecordAllLootItems( mobIndex, 0 )
	end
	MI2_LootFrameOpen = false
end

local function MI2_EventUnitCombat()
	if arg1 == "target" then
		if MI2_Target.index and arg4 > 0 then
			MI2_RecordTargetCombat( arg4, arg2 == "HEAL" )
		end
	elseif arg1 == "player" then
		if arg3 ~= "CRITICAL" and arg2 ~= "HEAL" and MI2_Target.mobIndex then 
			MI2_RecordDamage( MI2_Target.mobIndex, tonumber(arg4) )
		end
	end
end

local function MI2_EventUnitHealth()
	if arg1 == "target" then
		MI2_RecordTargetHealth( UnitHealth("target") )
	end
end

local function MI2_EventUnitMana()
	if arg1 == "target" then
		MobHealth_Display( )
	end
	if GameTooltip:IsShown() then
		MI2_UpdateTooltipHealthMana()
	end
end

function MI2_OnTargetChanged()
	local name = UnitName("target")
	local level = UnitLevel("target")
	MI2_IsNonMobLoot = false
	if  MI2_Target.mobIndex then
		MI2_SaveTargetHealthData()
		MI2_LastTargetIdx = MI2_Target.mobIndex
		if MI2_Target.FightStartTime then
			MI2_RecordDps( MI2_LastTargetIdx, MI2_Target.FightEndTime - MI2_Target.FightStartTime, MI2_Target.FightDamage )
		end
		if MobInfoConfig.SaveResist == 1 then
			MI2_StoreResistData( MI2_LastTargetIdx )
		end
	end
	if name and level and (UnitCanAttack("player","target") or UnitIsPlayer("target")) then
		MI2_Target = { name=name, level=level }
		MI2_Target.class = UnitClass("target")
		if  UnitIsPlayer("target")  then
			MI2_Target.index = name
			MI2_Target.healthDB = MobHealthPlayerDB
		else
			MI2_Target.index = name..":"..level
			MI2_Target.healthDB = MobHealthDB
			MI2_Target.mobIndex = MI2_Target.index
			MI2_RecordLocationAndType( MI2_Target.mobIndex )
			if level < (UnitLevel("player") + 5) then MI2_Target.ResOk = true end
			local mobData = MI2_FetchMobData( MI2_Target.index )
			mobData.killed = nil
		end
	else
		MI2_Target = {}
	end
	MI2_HpSetNewTarget()
	if frmMIConfig:IsVisible()  then
		MI2_DbOptionsFrameOnShow()
	end
	if MI2_DebugEvents > 0 then if MI2_Target then midebug( "new target: idx=["..(MI2_Target.index or "nil").."], last=["..(MI2_LastTargetIdx or "nil").."]" )
	else midebug( "new target: idx=[nil], last=["..(MI2_LastTargetIdx or "nil").."]" ) end end
end

local function MI2_EventSelfMelee( )
	if not MI2_Target.mobIndex then return end
	local s,e, mob, damage = string.find(arg1, MI2_ChatScanStrings[4])
	if not damage then
		s,e, mob, damage = string.find(arg1, MI2_ChatScanStrings[5])
	end
	if damage then
		MI2_RecordHit( tonumber(damage) )
	end
end

local function MI2_EventSelfSpell( )
	local isResist = false
	if not MI2_Target.mobIndex then return end
	local s,e, spell, mob, damage, school = string.find(arg1, MI2_ChatScanStrings[17])
	if not damage then
		s,e, spell, mob, damage, school = string.find(arg1, MI2_ChatScanStrings[7])
		if not damage then
			s,e, spell, mob, damage = string.find(arg1, MI2_ChatScanStrings[6])
			if not damage then
				s,e, spell, mob, damage = string.find(arg1, MI2_ChatScanStrings[8])
				if not damage then
					s,e, mob, spell = string.find(arg1, MI2_ChatScanStrings[14])
					if not spell then
						s,e, spell, mob = string.find(arg1, MI2_ChatScanStrings[15])
						if not mob then
							s,e, spell, mob = string.find(arg1, MI2_ChatScanStrings[16])
							isResist = true
	end end end end end end
	if damage then
		MI2_RecordHit( tonumber(damage), spell, school )
	elseif mob and spell then
		MI2_RecordImmunResist( mob, spell, isResist )
	end
end

local function MI2_EventPetMelee( )
	if not MI2_Target.mobIndex then return end
	local s,e, pet, mob, damage = string.find(arg1, MI2_ChatScanStrings[10])
	if not damage then
		s,e, pet, mob, damage = string.find(arg1, MI2_ChatScanStrings[11])
	end
	if damage then
		MI2_RecordHit( tonumber(damage) )
	end
end

local function MI2_EventPetSpell( )
	if not MI2_Target.mobIndex then return end
	local s,e, pet, spell, mob, damage = string.find(arg1, MI2_ChatScanStrings[12])
	if not damage then
		s,e, pet, spell, mob, damage = string.find(arg1, MI2_ChatScanStrings[13])
	end
	if damage then
		MI2_RecordHit( tonumber(damage) )
	end
end

local function MI2_EventSpellPeriodic()
	if not MI2_Target.mobIndex then return end
	local s,e, mob, damage, school, spell = string.find(arg1, MI2_ChatScanStrings[9])
	if not damage then
		s,e, mob, spell = string.find(arg1, MI2_ChatScanStrings[18])
	end
	if damage then
		MI2_RecordHit( damage, spell, school, true )
	else
		MI2_RecordHit( 0, spell, school )
	end
end

local function MI2_EventSpellPeriodic_ZHCN()
	if not MI2_Target.mobIndex then return end
	local s,e, spell, mob, damage, school = string.find(arg1, MI2_ChatScanStrings[9])
	if not damage then
		s,e, mob, spell = string.find(arg1, MI2_ChatScanStrings[18])
	end
	if damage then
		MI2_RecordHit( damage, spell, school, true )
	else
		MI2_RecordHit( 0, spell, school )
	end
end

local function MI2_EventSelfBuff()
	local s,e, lootAction, lootType = string.find( arg1, MI2_ChatScanStrings[1] )
	if lootAction and lootType then
		if MI2_DebugEvents > 0 then midebug("non mob loot event: action="..lootAction..", type="..lootType ) end
		MI2_IsNonMobLoot = true
	end
end

local function MI2_EventSelfBuff_ZHCN()
	local s,e, lootType, lootAction  = string.find( arg1, MI2_ChatScanStrings[1] )
	if lootAction and lootType then
		if MI2_DebugEvents > 0 then midebug("non mob loot event: action="..lootAction..", type="..lootType ) end
		MI2_IsNonMobLoot = true
	end
end

local function MI2_EventHostileDeath()
	local s,e, creatureName = string.find( arg1, MI2_ChatScanStrings[2] )
	if creatureName then
		if MI2_DebugEvents > 0 then midebug("no XP kill event: mob="..creatureName ) end
		MI2_RecordKill( creatureName )
	end
end

function MI2_EventCreatureDiesXP()
	local s,e, creature, xp = string.find( arg1, MI2_ChatScanStrings[3] )
	if creature and xp then
		if MI2_DebugEvents > 0 then midebug("kill event with XP: mob="..creature..", xp="..xp ) end
		MI2_RecordKill( creature, tonumber(xp) )
	end
end

local function MI2_EventMonsterEmote()
	local s,e = string.find( arg1, MI2_CHATMSG_MONSTEREMOTE )
	if s then
		MI2_RecordLowHpAction( arg2, 1 )
	end
end

local function MI2_EventZoneChanged()
	MI2_SetNewZone( GetZoneText() )
end

local function MI2_Player_Login()
	MI2_EventZoneChanged()
	MI2_ScanSpellbook()
	if not (myAddOnsFrame_Register or EarthFeature_AddButton or Khaos) then
		chattext( "MobInfo-2  v"..miVersionNo.."  Loaded,  ".."enter /mi2 or /mobinfo2 for interface")
	end
end

function MI2_GameTooltip_OnShow( )
	MI2_HealthLine, MI2_ManaLine = nil, nil
	if MobInfoConfig.DisableMobInfo == 0 and (MobInfoConfig.KeypressMode == 0
			or MobInfoConfig.KeypressMode == 1 and IsAltKeyDown())  then
		local firstline = getglobal("GameTooltipTextLeft1");
		if  UnitCreatureType("mouseover") and UnitIsFriend("player","mouseover") == nil then
			MI2_BuildMobInfoTooltip( UnitName("mouseover"), UnitLevel("mouseover"), nil )
			GameTooltip:Show()
		elseif firstline and UnitClass("mouseover") == nil then
			if MI2_BuildItemDataTooltip( firstline:GetText() ) then
				GameTooltip:Show()
			end
		end
	end
	if MI2_GT_OnShow_Orig then
		MI2_GT_OnShow_Orig(event)
	end
end

function MI2_InitializeEventTable()
	for eventName, eventInfo in pairs(MI2_EventHandlers) do
		local eventEnabled = eventInfo.always
								or MobInfoConfig.SaveBasicInfo == 1 and eventInfo.basic
								or MobInfoConfig.SaveCharData == 1 and eventInfo.char
								or MobInfoConfig.SaveItems == 1 and eventInfo.items
								or MobInfoConfig.SaveLocation == 1 and eventInfo.loc
		if eventEnabled then
			this:RegisterEvent( eventName )
		end
	end
end

function MI2_OnEvent( event )
	MI2_EventHandlers[event].f()
end

function MI2_OnLoad()
	MI2_EventHandlers = {
		VARIABLES_LOADED = {f=MI2_VariablesLoaded, on=1},
		UNIT_COMBAT = {f=MI2_EventUnitCombat, always=1},
		UNIT_HEALTH = {f=MI2_EventUnitHealth, always=1},
		UNIT_MANA = {f=MI2_EventUnitMana, always=1},
		PLAYER_TARGET_CHANGED = {f=MI2_OnTargetChanged, always=1},
		PLAYER_LOGIN = {f=MI2_Player_Login, always=1},
		LOOT_OPENED = {f=MI2_EventLootOpened, basic=1, items=1},
		LOOT_CLOSED = {f=MI2_EventLootClosed, basic=1, items=1},
		LOOT_SLOT_CLEARED = {f=MI2_EventLootSlotCleared, basic=1, items=1},
		CHAT_MSG_SPELL_SELF_BUFF = {f=MI2_EventSelfBuff, basic=1, items=1},
		CHAT_MSG_COMBAT_XP_GAIN = {f=MI2_EventCreatureDiesXP, basic=1},
		ZONE_CHANGED_NEW_AREA = {f=MI2_EventZoneChanged, loc=1},
		ZONE_CHANGED_INDOORS = {f=MI2_EventZoneChanged, loc=1},
		CHAT_MSG_COMBAT_HOSTILE_DEATH = {f=MI2_EventHostileDeath, char=1},
		CHAT_MSG_COMBAT_SELF_HITS = {f=MI2_EventSelfMelee, char=1},
		CHAT_MSG_SPELL_SELF_DAMAGE = {f=MI2_EventSelfSpell, char=1},
		CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE = {f=MI2_EventSpellPeriodic, char=1},
		CHAT_MSG_COMBAT_PET_HITS = {f=MI2_EventPetMelee, char=1},
		CHAT_MSG_SPELL_PET_DAMAGE = {f=MI2_EventPetSpell, char=1},
		CHAT_MSG_MONSTER_EMOTE = {f=MI2_EventMonsterEmote, basic=1}, }
	if ( GetLocale() == "zhCN" ) then
		MI2_EventHandlers.CHAT_MSG_SPELL_PERIODIC_CREATURE_DAMAGE.f = MI2_EventSpellPeriodic_ZHCN
		MI2_EventHandlers.CHAT_MSG_SPELL_SELF_BUFF.f = MI2_EventSelfBuff_ZHCN
	end
	MI2_ChatScanStrings = {
		[1] = OPEN_LOCK_SELF,
		[2] = SELFKILLOTHER,
		[3] = COMBATLOG_XPGAIN_FIRSTPERSON,
		[4] = COMBATHITSELFOTHER,
		[5] = COMBATHITCRITSELFOTHER,
		[6] = SPELLLOGSELFOTHER,
		[7] = SPELLLOGSCHOOLSELFOTHER,
		[8] = SPELLLOGCRITSELFOTHER,
		[9] = PERIODICAURADAMAGESELFOTHER,
		[10] = COMBATHITOTHEROTHER,
		[11] = COMBATHITCRITOTHEROTHER,
		[12] = SPELLLOGOTHEROTHER,
		[13] = SPELLLOGCRITOTHEROTHER,
		[14] = IMMUNESPELLSELFOTHER,
		[15] = SPELLIMMUNESELFOTHER,
		[16] = SPELLRESISTSELFOTHER,
		[17] = SPELLLOGCRITSCHOOLSELFOTHER,
		[18] = AURAADDEDOTHERHARMFUL, }
	for idx, scanString in pairs(MI2_ChatScanStrings) do
		scanString = string.gsub(scanString, "%(", "%%%(")
		scanString = string.gsub(scanString, "%)", "%%%)")
		scanString = string.gsub(scanString, "(%%s)", "%(%.%+%)")
		scanString = string.gsub(scanString, "(%%%d$s)", "%(%.%+%)")
		scanString = string.gsub(scanString, "(%%d)", "%(%%%d%+%)")
		scanString = string.gsub(scanString, "(%%%d$d)", "%(%%%d%+%)")
		MI2_ChatScanStrings[idx] = scanString
	end
	this:RegisterEvent("VARIABLES_LOADED")
	MI2_PrepareForImport()
	MI2_DeleteAllMobData()
	MobHealthDB	= {}
	MobHealthPlayerDB = {}
	if  not MobHealth_OnEvent  then
		MobHealthFrame = "MI2"
		MobHealth_OnEvent = MI2_OnEvent
	end
end