
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
local _detalhes = 		_G._detalhes
local Loc = LibStub("AceLocale-3.0"):GetLocale( "Details" )
local SharedMedia = LibStub:GetLibrary("LibSharedMedia-3.0")
local _tempo = time()
local _

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> local pointers

local _math_floor = math.floor --lua local
local _math_max = math.max --lua local
local _ipairs = ipairs --lua local
local _pairs = pairs --lua local
local _table_wipe = table.wipe --lua local
local _bit_band = bit.band --lua local

local _GetInstanceInfo = GetInstanceInfo --wow api local
local _GetCurrentMapAreaID = GetCurrentMapAreaID --wow api local
local _GetRealZoneText = GetRealZoneText --wow api local
local _GetInstanceDifficulty = GetInstanceDifficulty --wow api local
local _UnitExists = UnitExists --wow api local
local _UnitGUID = UnitGUID --wow api local
local _UnitName = UnitName --wow api local
local _GetTime = GetTime

local _IsAltKeyDown = IsAltKeyDown
local _IsShiftKeyDown = IsShiftKeyDown
local _IsControlKeyDown = IsControlKeyDown

local atributo_damage = _detalhes.atributo_damage --details local
local atributo_heal = _detalhes.atributo_heal --details local
local atributo_energy = _detalhes.atributo_energy --details local
local atributo_misc = _detalhes.atributo_misc --details local
local atributo_custom = _detalhes.atributo_custom --details local
local info = _detalhes.janela_info --details local

local UnitGroupRolesAssigned = DetailsFramework.UnitGroupRolesAssigned

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> constants

local modo_GROUP = _detalhes.modos.group
local modo_ALL = _detalhes.modos.all
local class_type_dano = _detalhes.atributos.dano
local OBJECT_TYPE_PETS = 0x00003000

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> details api functions

--> try to find the opponent of last fight, can be called during a fight as well
function _detalhes:FindEnemy()
	local ZoneName, InstanceType = _GetInstanceInfo()
	local ZoneMapID = _GetCurrentMapAreaID()
	local in_instance = IsInInstance() --> garrison returns party as instance type.

	if (InstanceType == "party" or InstanceType == "raid") and in_instance then
		if InstanceType == "party" then
			if _detalhes:GetBossNames(_detalhes.zone_id) then
				return Loc["STRING_SEGMENT_TRASH"]
			end
		else
			return Loc["STRING_SEGMENT_TRASH"]
		end
	end

	for _, actor in _ipairs(_detalhes.tabela_vigente[class_type_dano]._ActorTable) do
		if not actor.grupo and not actor.owner and not actor.nome:find("[*]") and _bit_band(actor.flag_original, 0x00000060) ~= 0 then --> 0x20+0x40 neutral + enemy reaction
			for name, _ in _pairs(actor.targets) do
				if name == _detalhes.playername then
					return actor.nome
				else
					local _target_actor = _detalhes.tabela_vigente(class_type_dano, name)
					if _target_actor and _target_actor.grupo then
						return actor.nome
					end
				end
			end
		end

	end

	for _, actor in _ipairs(_detalhes.tabela_vigente[class_type_dano]._ActorTable) do
		if actor.grupo and not actor.owner then
			for target_name, _ in _pairs(actor.targets) do
				return target_name
			end
		end
	end

	return Loc["STRING_UNKNOW"]
end

local boss_found = function(index, name, zone, mapid, diff, encounterid)
	local mapID = GetCurrentMapAreaID()
	if not mapID then
		--print("Details! exeption handled: zone has no map")
		return
	end

	local boss_table = {
		index = index,
		name = name,
		encounter = name,
		zone = zone,
		mapid = mapid,
		diff = diff,
		diff_string = select(4, GetInstanceInfo()),
		id = encounterid,
	}

	if not _detalhes:IsRaidRegistered(mapid) and _detalhes.zone_type == "raid" then
		local boss_list = _detalhes:GetCurrentDungeonBossListFromEJ()
		if boss_list then
			local ActorsContainer = _detalhes.tabela_vigente[class_type_dano]._ActorTable
			if ActorsContainer then
				for index, Actor in _ipairs(ActorsContainer) do
					if not Actor.grupo then
						if boss_list[Actor.nome] then
							Actor.boss = true
							boss_table.bossimage = boss_list[Actor.nome][4]
							break
						end
					end
				end
			end
		end
	end

	_detalhes.tabela_vigente.is_boss = boss_table

	if _detalhes.in_combat and not _detalhes.leaving_combat then
		--> catch boss function if any
		local bossFunction, bossFunctionType = _detalhes:GetBossFunction(mapID, index)
		if bossFunction then
			if _bit_band(bossFunctionType, 0x1) ~= 0 then --realtime
				_detalhes.bossFunction = bossFunction
				_detalhes.tabela_vigente.bossFunction = _detalhes:ScheduleTimer("bossFunction", 1)
			end
		end

		if _detalhes.zone_type ~= "raid" then
			local endType, endData = _detalhes:GetEncounterEnd(mapID, index)
			if endType and endData then

				if _detalhes.debug then
					_detalhes:Msg("(debug) setting boss end type to:", endType)
				end

				_detalhes.encounter_end_table.type = endType
				_detalhes.encounter_end_table.killed = {}
				_detalhes.encounter_end_table.data = {}

				if type(endData) == "table" then
					if _detalhes.debug then
						_detalhes:Msg("(debug) boss type is table:", endType)
					end

					if endType == 1 or endType == 2 then
						for _, npcID in ipairs(endData) do
							_detalhes.encounter_end_table.data[npcID] = false
						end
					end
				else
					if endType == 1 or endType == 2 then
						_detalhes.encounter_end_table.data[endData] = false
					end
				end
			end
		end
	end

	--> we the boss was found during the combat table creation, we must postpone the event trigger
	if not _detalhes.tabela_vigente.IsBeingCreated then
		_detalhes:SendEvent("COMBAT_BOSS_FOUND", nil, index, name)
		_detalhes:CheckFor_SuppressedWindowsOnEncounterFound()
	end

	return boss_table
end

function _detalhes:ReadBossFrames()
	if _detalhes.tabela_vigente.is_boss then
		return --no need to check
	end

	if _detalhes.encounter_table.name then
		local encounter_table = _detalhes.encounter_table
		return boss_found(encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id)
	end

	for index = 1, 4, 1 do
		if _UnitExists("boss"..index) then
			local guid = _UnitGUID("boss"..index)
			if guid then
				local serial = _detalhes:GetNpcIdFromGuid(guid)
				if serial then
					local ZoneName = _GetInstanceInfo()
					local DifficultyID = _GetInstanceDifficulty()
					local ZoneMapID = _GetCurrentMapAreaID()
					local BossIds = _detalhes:GetBossIds(ZoneMapID)
					if BossIds then
						local BossIndex = BossIds[serial]
						if BossIndex then
							if _detalhes.debug then
								_detalhes:Msg("(debug) boss found:",_detalhes:GetBossName(ZoneMapID, BossIndex))
							end

							return boss_found(BossIndex, _detalhes:GetBossName(ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID)
						end
					end
				end
			end
		end
	end
end

--try to get the encounter name after the encounter(can be called during the combat as well)
function _detalhes:FindBoss()
	if _detalhes.encounter_table.name then
		local encounter_table = _detalhes.encounter_table
		return boss_found(encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id)
	end

	local ZoneName, InstanceType = _GetInstanceInfo()
	local ZoneMapID = _GetCurrentMapAreaID()
	local DifficultyID = _GetInstanceDifficulty()
	local BossIds = _detalhes:GetBossIds(ZoneMapID)
	if not BossIds then
		for id, data in _pairs(_detalhes.EncounterInformation) do
			if data.name == ZoneName then
				BossIds = _detalhes:GetBossIds(id)
				ZoneMapID = id
				break
			end
		end
	end

	if BossIds then
		local BossIndex = nil
		local ActorsContainer = _detalhes.tabela_vigente[class_type_dano]._ActorTable

		if ActorsContainer then
			for index, Actor in _ipairs(ActorsContainer) do
				if not Actor.grupo then
					local serial = _detalhes:GetNpcIdFromGuid(Actor.serial)
					if serial then
						BossIndex = BossIds[serial]
						if BossIndex then
							Actor.boss = true
							return boss_found(BossIndex, _detalhes:GetBossName(ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID)
						end
					end
				end
			end
		end
	end

	return false
end

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> internal functions
-- _detalhes.statistics = {container_calls = 0, container_pet_calls = 0, container_unknow_pet = 0, damage_calls = 0, heal_calls = 0, absorbs_calls = 0, energy_calls = 0, pets_summons = 0}

function _detalhes:StartCombat(...)
	return _detalhes:EntrarEmCombate(...)
end

-- ~start ~inicio ~novo �ovo
function _detalhes:EntrarEmCombate(...)
	if _detalhes.debug then
		_detalhes:Msg("(debug) |cFFFFFF00started a new combat|r|cFFFF7700", _detalhes.encounter_table and _detalhes.encounter_table.name or "")
--		local from = debugstack(2, 1, 0)
--		print(from)
	end

	if not _detalhes.tabela_historico.tabelas[1] then
		_detalhes.tabela_overall = _detalhes.combate:NovaTabela()

		_detalhes:InstanciaCallFunction(_detalhes.ResetaGump, nil, -1) --> reseta scrollbar, iterators, rodap�, etc
		_detalhes:InstanciaCallFunction(_detalhes.InstanciaFadeBarras, -1) --> esconde todas as barras
		_detalhes:InstanciaCallFunction(_detalhes.AtualizaSegmentos) --> atualiza o showing
	end

	--> re-lock nos tempos da tabela passada -- lock again last table times
	_detalhes.tabela_vigente:TravarTempos()

	local n_combate = _detalhes:NumeroCombate(1) --aumenta o contador de combates -- combat number up

	--> cria a nova tabela de combates -- create new table
	local ultimo_combate = _detalhes.tabela_vigente
	_detalhes.tabela_vigente = _detalhes.combate:NovaTabela(true, _detalhes.tabela_overall, n_combate, ...) --cria uma nova tabela de combate

	--> flag this combat as being created
	_detalhes.tabela_vigente.IsBeingCreated = true

	_detalhes.tabela_vigente.previous_combat = ultimo_combate

	_detalhes.tabela_vigente:seta_data(_detalhes._detalhes_props.DATA_TYPE_START) --seta na tabela do combate a data do inicio do combate -- setup time data
	_detalhes.in_combat = true --sinaliza ao addon que h� um combate em andamento -- in combat flag up
	_detalhes.tabela_vigente.combat_id = n_combate --> grava o n�mero deste combate na tabela atual -- setup combat id on new table
	_detalhes.last_combat_pre_pot_used = nil

	_detalhes:FlagCurrentCombat()

	--> � o timer que ve se o jogador ta em combate ou n�o -- check if any party or raid members are in combat
	_detalhes.tabela_vigente.verifica_combate = _detalhes:ScheduleRepeatingTimer("EstaEmCombate", 1)

	_detalhes:ClearCCPetsBlackList()

	_table_wipe(_detalhes.encounter_end_table)

	_table_wipe(_detalhes.pets_ignored)
	_table_wipe(_detalhes.pets_no_owner)
	_detalhes.container_pets:BuscarPets()

	_table_wipe(_detalhes.cache_dead_npc)
	_table_wipe(_detalhes.cache_damage_group)
	_table_wipe(_detalhes.cache_healing_group)
	_detalhes:UpdateParserGears()

	--> get all buff already applied before the combat start
	_detalhes:CatchRaidBuffUptime("BUFF_UPTIME_IN")
	_detalhes:CatchRaidDebuffUptime("DEBUFF_UPTIME_IN")
	_detalhes:UptadeRaidMembersCache()

	--> we already have boss information? build .is_boss table
	if _detalhes.encounter_table.id and _detalhes.encounter_table["start"] and not _detalhes.encounter_table["end"] then
		local encounter_table = _detalhes.encounter_table
		--> boss_found will trigger "COMBAT_BOSS_FOUND" event, but at this point of the combat creation is safe to send it
		boss_found(encounter_table.index, encounter_table.name, encounter_table.zone, encounter_table.mapid, encounter_table.diff, encounter_table.id)
	else
		--> if we don't have this infor right now, lets check in few seconds dop
		if _detalhes:IsInInstance() then
			_detalhes:ScheduleTimer("ReadBossFrames", 1)
			_detalhes:ScheduleTimer("ReadBossFrames", 30)
		end
	end

	--> if the window is showing current segment, switch it for the new combat
	--> also if the window has auto current, jump to current segment
	_detalhes:InstanciaCallFunction(_detalhes.TrocaSegmentoAtual, _detalhes.tabela_vigente.is_boss and true)

	--> clear hosts and make the cloud capture stuff
	_detalhes.host_of = nil
	_detalhes.host_by = nil

	if _detalhes.in_group and _detalhes.cloud_capture then
		if _detalhes:IsInInstance() or _detalhes.debug then
			if not _detalhes:CaptureIsAllEnabled() then
				_detalhes:ScheduleSendCloudRequest()

--				if _detalhes.debug then
--					_detalhes:Msg("(debug) requesting a cloud server.")
--				end
			end
		else
--			if _detalhes.debug then
--				_detalhes:Msg("(debug) isn't inside a registred instance", _detalhes:IsInInstance())
--			end
		end
	else
--		if _detalhes.debug then
--			_detalhes:Msg("(debug) isn't in group or cloud is turned off", _detalhes.in_group, _detalhes.cloud_capture)
--		end
	end

	--> hide / alpha / switch in combat
	for index, instancia in ipairs(_detalhes.tabela_instancias) do
		if instancia.ativa then
			--instancia:SetCombatAlpha(nil, nil, true) --passado para o regen disable
			instancia:CheckSwitchOnCombatStart(true)
		end
	end

	_detalhes:InstanceCall(_detalhes.CheckPsUpdate)

	--> combat creation is completed, remove the flag
	_detalhes.tabela_vigente.IsBeingCreated = nil

	_detalhes:SendEvent("COMBAT_PLAYER_ENTER", nil, _detalhes.tabela_vigente, _detalhes.encounter_table and _detalhes.encounter_table.id)

	if _detalhes.tabela_vigente.is_boss then
		--> the encounter was found through encounter_start event
		_detalhes:SendEvent("COMBAT_BOSS_FOUND", nil, _detalhes.tabela_vigente.is_boss.index, _detalhes.tabela_vigente.is_boss.name)
	end

	_detalhes:CheckSwitchToCurrent()
	_detalhes:CheckForTextTimeCounter(true)

	--> stop bar testing if any
	_detalhes:StopTestBarUpdate()
end

function _detalhes:DelayedSyncAlert()
	local lower_instance = _detalhes:GetLowerInstanceNumber()
	if lower_instance then
		lower_instance = _detalhes:GetInstance(lower_instance)
		if lower_instance then
			if not lower_instance:HaveInstanceAlert() then
				lower_instance:InstanceAlert(Loc["STRING_EQUILIZING"], {[[Interface\COMMON\StreamCircle]], 22, 22, true}, 5, {function() end})
			end
		end
	end
end

function _detalhes:ScheduleSyncPlayerActorData()
	if (IsInGroup() or IsInRaid()) and (_detalhes.zone_type == "party" or _detalhes.zone_type == "raid") then
		--> do not sync if in battleground or arena
		_detalhes:SendCharacterData()
	end
end

function _detalhes:EndCombat()
	if _detalhes.in_combat then
		_detalhes:SairDoCombate()
	end
end

-- ~end ~leave
function _detalhes:SairDoCombate(bossKilled, from_encounter_end)
	if _detalhes.debug then
		_detalhes:Msg("(debug) |cFFFFFF00ended a combat|r|cFFFF7700", _detalhes.encounter_table and _detalhes.encounter_table.name or "")
	end

	--> in case of something somehow someway call to close the same combat a second time.
	if _detalhes.tabela_vigente == _detalhes.last_closed_combat then
		return
	end

	_detalhes.last_closed_combat = _detalhes.tabela_vigente

--	if _detalhes.statistics then
--		for k, v in pairs(_detalhes.statistics) do
--			print(k, v)
--		end
--	end

	_detalhes.leaving_combat = true
	_detalhes.last_combat_time = _tempo

	--deprecated(combat are now added immediatelly since there's no script run too long)
--	if _detalhes.schedule_remove_overall and not from_encounter_end and not InCombatLockdown() then
--		if _detalhes.debug then
--			_detalhes:Msg("(debug) found schedule overall data deletion.")
--		end
--
--		_detalhes.schedule_remove_overall = false
--		_detalhes.tabela_historico:resetar_overall()
--	end

	_detalhes:CatchRaidBuffUptime("BUFF_UPTIME_OUT")
	_detalhes:CatchRaidDebuffUptime("DEBUFF_UPTIME_OUT")
	_detalhes:CloseEnemyDebuffsUptime()

	--> check if this isn't a boss and try to find a boss in the segment
	if not _detalhes.tabela_vigente.is_boss then
		_detalhes:FindBoss()

		--> still didn't find the boss
		if not _detalhes.tabela_vigente.is_boss then
			local ZoneName = _GetInstanceInfo()
			local ZoneMapID = _GetCurrentMapAreaID()
			local DifficultyID = _GetInstanceDifficulty()
			local findboss = _detalhes:GetRaidBossFindFunction(ZoneMapID)
			if findboss then
				local BossIndex = findboss()
				if BossIndex then
					boss_found(BossIndex, _detalhes:GetBossName(ZoneMapID, BossIndex), ZoneName, ZoneMapID, DifficultyID)
				end
			end
		end
	end

	if _detalhes.tabela_vigente.bossFunction then
		_detalhes:CancelTimer(_detalhes.tabela_vigente.bossFunction)
		_detalhes.tabela_vigente.bossFunction = nil
	end

	--> finaliza a checagem se esta ou n�o no combate -- finish combat check
	if _detalhes.tabela_vigente.verifica_combate then
		_detalhes:CancelTimer(_detalhes.tabela_vigente.verifica_combate)
		_detalhes.tabela_vigente.verifica_combate = nil
	end

	--> lock timers
	_detalhes.tabela_vigente:TravarTempos()

	--> get waste shields
--	if _detalhes.close_shields then
--		_detalhes:CloseShields(_detalhes.tabela_vigente)
--	end

	--> salva hora, minuto, segundo do fim da luta
	_detalhes.tabela_vigente:seta_data(_detalhes._detalhes_props.DATA_TYPE_END)
	_detalhes.tabela_vigente:seta_tempo_decorrido()

	--> drop last events table to garbage collector
	_detalhes.tabela_vigente.player_last_events = {}

	--> flag instance type
	local _, InstanceType = _GetInstanceInfo()
	_detalhes.tabela_vigente.instance_type = InstanceType

	if not _detalhes.tabela_vigente.is_boss and from_encounter_end and type(from_encounter_end) == "table" then
		local encounterID, encounterName, difficultyID, raidSize, endStatus = unpack(from_encounter_end)
		if encounterID then
			local ZoneName, InstanceType, _, DifficultyName = GetInstanceInfo()
			local DifficultyID = _GetInstanceDifficulty()
			local ZoneMapID = _GetCurrentMapAreaID()

			local _, boss_index = _detalhes:GetBossEncounterDetailsFromEncounterId(ZoneMapID, encounterID)

			_detalhes.tabela_vigente.is_boss = {
				index = boss_index or 0,
				name = encounterName,
				encounter = encounterName,
				zone = ZoneName,
				mapid = ZoneMapID,
				diff = DifficultyID,
				diff_string = DifficultyName,
				id = encounterID,
			}
		end
	end

	--> send item level after a combat if is in raid or party group
	_detalhes:ScheduleTimer("ScheduleSyncPlayerActorData", 1)

	--if this segment isn't a boss fight
	if not _detalhes.tabela_vigente.is_boss then
		if _detalhes.tabela_vigente.is_pvp or _detalhes.tabela_vigente.is_arena then
			_detalhes:FlagActorsOnPvPCombat()
		end

		if _detalhes.tabela_vigente.is_arena then
			_detalhes.tabela_vigente.enemy = "["..ARENA.."] ".._detalhes.tabela_vigente.is_arena.name
		end

		local in_instance = IsInInstance() --> garrison returns party as instance type.
		if (InstanceType == "party" or InstanceType == "raid") and in_instance then
			if InstanceType == "party" then
				--> tag the combat as trash clean up
				_detalhes.tabela_vigente.is_trash = true
			else
				_detalhes.tabela_vigente.is_trash = true
			end
		else
			if not in_instance then
				if _detalhes.world_combat_is_trash then
					_detalhes.tabela_vigente.is_temporary = true
				end
			end
		end

		if not _detalhes.tabela_vigente.enemy then
			local enemy = _detalhes:FindEnemy()

			if enemy and _detalhes.debug then
				_detalhes:Msg("(debug) enemy found", enemy)
			end

			_detalhes.tabela_vigente.enemy = enemy
		end

		if _detalhes.debug then
--			_detalhes:Msg("(debug) forcing equalize actors behavior.")
--			_detalhes:EqualizeActorsSchedule(_detalhes.host_of)
		end

		--> verifica memoria
		_detalhes:FlagActorsOnCommonFight() --fight_component
--		_detalhes:CheckMemoryAfterCombat() -- 7.2.5 is doing some weird errors even out of combat
	else
		--this segment is a boss fight
		if not InCombatLockdown() and not UnitAffectingCombat("player") then

		else
--			_detalhes.schedule_flag_boss_components = true
		end

		--calling here without checking for combat since the does not ran too long for scripts
		_detalhes:FlagActorsOnBossFight()

		local boss_id = _detalhes.encounter_table.id
		if bossKilled then
			_detalhes.tabela_vigente.is_boss.killed = true

			--> add to storage
			if not InCombatLockdown() and not UnitAffectingCombat("player") and not _detalhes.logoff_saving_data then
--				_detalhes.StoreEncounter()
				local successful, errortext = pcall(_detalhes.StoreEncounter)
				if not successful then
					_detalhes:Msg("error occurred on StoreEncounter():", errortext)
				end
			else
				_detalhes.schedule_store_boss_encounter = true
			end

			_detalhes:SendEvent("COMBAT_BOSS_DEFEATED", nil, _detalhes.tabela_vigente)

			_detalhes:CheckFor_TrashSuppressionOnEncounterEnd()
		else
			_detalhes:SendEvent("COMBAT_BOSS_WIPE", nil, _detalhes.tabela_vigente)
		end

--		if _detalhes:GetBossDetails(_detalhes.tabela_vigente.is_boss.mapid, _detalhes.tabela_vigente.is_boss.index) or  then
			_detalhes.tabela_vigente.is_boss.index = _detalhes.tabela_vigente.is_boss.index or 1

			_detalhes.tabela_vigente.enemy = _detalhes.tabela_vigente.is_boss.encounter

			if _detalhes.tabela_vigente.instance_type == "raid" then
				_detalhes.last_encounter2 = _detalhes.last_encounter
				_detalhes.last_encounter = _detalhes.tabela_vigente.is_boss.name

				if _detalhes.pre_pot_used then
					_detalhes.last_combat_pre_pot_used = table_deepcopy(_detalhes.pre_pot_used)
				end

				if _detalhes.pre_pot_used and _detalhes.announce_prepots.enabled then
					_detalhes:Msg(_detalhes.pre_pot_used or "")
					_detalhes.pre_pot_used = nil
				end
			end

			if from_encounter_end then
				if _detalhes.encounter_table.start then
					_detalhes.tabela_vigente:SetStartTime(_detalhes.encounter_table.start)
				end
				_detalhes.tabela_vigente:SetEndTime(_detalhes.encounter_table["end"] or GetTime())
			end

			--> encounter boss function
			local bossFunction, bossFunctionType = _detalhes:GetBossFunction(_detalhes.tabela_vigente.is_boss.mapid or 0, _detalhes.tabela_vigente.is_boss.index or 0)
			if bossFunction then
				if _bit_band(bossFunctionType, 0x2) ~= 0 then --end of combat
					if not _detalhes.logoff_saving_data then
						local successful, errortext = pcall(bossFunction, _detalhes.tabela_vigente)
						if not successful then
							_detalhes:Msg("error occurred on Encounter Boss Function:", errortext)
						end
					end
				end
			end

			if _detalhes.tabela_vigente.instance_type == "raid" then
				--> schedule captures off
				_detalhes:CaptureSet(false, "damage", false, 15)
				_detalhes:CaptureSet(false, "energy", false, 15)
				_detalhes:CaptureSet(false, "aura", false, 15)
				_detalhes:CaptureSet(false, "energy", false, 15)
				_detalhes:CaptureSet(false, "spellcast", false, 15)

				if _detalhes.debug then
					_detalhes:Msg("(debug) freezing parser for 15 seconds.")
				end
			end

			--> schedule sync
			_detalhes:EqualizeActorsSchedule(_detalhes.host_of)
			if _detalhes:GetEncounterEqualize(_detalhes.tabela_vigente.is_boss.mapid, _detalhes.tabela_vigente.is_boss.index) then
				_detalhes:ScheduleTimer("DelayedSyncAlert", 3)
			end
--		else
--			if _detalhes.debug then
--				_detalhes:EqualizeActorsSchedule(_detalhes.host_of)
--			end
--		end
	end

	if _detalhes.solo then
		--> debuffs need a checkup, not well functional right now
		_detalhes.CloseSoloDebuffs()
	end

	local tempo_do_combate = _detalhes.tabela_vigente:GetCombatTime()
	local invalid_combat

	-- TEMP
	local zoneName, zoneType = GetInstanceInfo()
	if not _detalhes.tabela_vigente.discard_segment and(zoneType == "none" or tempo_do_combate >= _detalhes.minimum_combat_time or not _detalhes.tabela_historico.tabelas[1]) then
		_detalhes.tabela_historico:adicionar(_detalhes.tabela_vigente) --move a tabela atual para dentro do hist�rico
		--8.0.1 miss data isn't required at the moment, spells like akari's soul has been removed from the game
		--_detalhes:CanSendMissData()

		if _detalhes.tabela_vigente.is_boss then
			if IsInRaid() then
				local cleuID = _detalhes.tabela_vigente.is_boss.id
				local diff = _detalhes.tabela_vigente.is_boss.diff
				if cleuID and (diff == 1 or diff == 2 or diff == 3 or diff == 4) then
					local raidData = _detalhes.raid_data

					--get or build diff raid data table
					local diffRaidData = raidData[diff]
					if(not diffRaidData) then
						diffRaidData = {}
						raidData[diff] = diffRaidData
					end

					--get or build a table for this cleuID
					diffRaidData[cleuID] = diffRaidData[cleuID] or {wipes = 0, kills = 0, best_try = 1, longest = 0, try_history = {}}
					local cleuIDData = diffRaidData[cleuID]

					--store encounter data for plugins and weakauras
					if _detalhes.tabela_vigente:GetCombatTime() > cleuIDData.longest then
						cleuIDData.longest = _detalhes.tabela_vigente:GetCombatTime()
					end

					if _detalhes.tabela_vigente.is_boss.killed then
						cleuIDData.kills = cleuIDData.kills + 1
						cleuIDData.best_try = 0
						tinsert(cleuIDData.try_history, {0, _detalhes.tabela_vigente:GetCombatTime()})

--						print("KILL", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest)
					else
						cleuIDData.wipes = cleuIDData.wipes + 1
						if _detalhes.boss1_health_percent and _detalhes.boss1_health_percent < cleuIDData.best_try then
							cleuIDData.best_try = _detalhes.boss1_health_percent
							tinsert(cleuIDData.try_history, {_detalhes.boss1_health_percent, _detalhes.tabela_vigente:GetCombatTime()})
						end

--						print("WIPE", "best try", cleuIDData.best_try, "amt kills", cleuIDData.kills, "wipes", cleuIDData.wipes, "longest", cleuIDData.longest)
					end
				end
			end
			--
		end

		--the combat is valid, see if the user is sharing data with somebody
		if _detalhes.shareData then
			local zipData = Details:CompressData(_detalhes.tabela_vigente, "comm")
			if zipData then
				print("has zip data")
			end
		end
	else
		invalid_combat = _detalhes.tabela_vigente

		--> tutorial about the combat time < then 'minimum_combat_time'
		local hasSeenTutorial = _detalhes:GetTutorialCVar("MIN_COMBAT_TIME")
		if not hasSeenTutorial then
			local lower_instance = _detalhes:GetLowerInstanceNumber()
			if lower_instance then
				lower_instance = _detalhes:GetInstance(lower_instance)
				if lower_instance then
					lower_instance:InstanceAlert("combat ignored: less than 5 seconds.", {[[Interface\BUTTONS\UI-GROUPLOOT-PASS-DOWN]], 18, 18, false, 0, 1, 0, 1}, 20, {function() Details:Msg("combat ignored: elapsed time less than 5 seconds."); Details:Msg("add '|cFFFFFF00Details.minimum_combat_time = 2;|r' on Auto Run Code to change the minimum time.") end})
					_detalhes:SetTutorialCVar("MIN_COMBAT_TIME", true)
				end
			end
		end

		--in case of a forced discard segment, just check a second time if we have a previous combat.
		if not _detalhes.tabela_historico.tabelas[1] then
			_detalhes.tabela_vigente = _detalhes.tabela_vigente
		else
			_detalhes.tabela_vigente = _detalhes.tabela_historico.tabelas[1] --> pega a tabela do ultimo combate
		end

		if _detalhes.tabela_vigente:GetStartTime() == 0 then
			--_detalhes.tabela_vigente.start_time = _detalhes._tempo
			_detalhes.tabela_vigente:SetStartTime(_GetTime())
			--_detalhes.tabela_vigente.end_time = _detalhes._tempo
			_detalhes.tabela_vigente:SetEndTime(_GetTime())
		end

		_detalhes.tabela_vigente.resincked = true

		--> tabela foi descartada, precisa atualizar os baseframes // precisa atualizer todos ou apenas o overall?
		_detalhes:InstanciaCallFunction(_detalhes.AtualizarJanela)

		if _detalhes.solo then
			local esta_instancia = _detalhes.tabela_instancias[_detalhes.solo]
			if _detalhes.SoloTables.CombatID == _detalhes:NumeroCombate() then --> significa que o solo mode validou o combate, como matar um bixo muito low level com uma s� porrada
				if _detalhes.SoloTables.CombatIDLast and _detalhes.SoloTables.CombatIDLast ~= 0 then --> volta os dados da luta anterior
					_detalhes.SoloTables.CombatID = _detalhes.SoloTables.CombatIDLast
				else
					if _detalhes.RefreshSolo then
						_detalhes:RefreshSolo()
					end

					_detalhes.SoloTables.CombatID = nil
				end
			end
		end

		_detalhes:NumeroCombate(-1)
	end

	_detalhes.host_of = nil
	_detalhes.host_by = nil

	if _detalhes.cloud_process then
		_detalhes:CancelTimer(_detalhes.cloud_process)
	end

	_detalhes.in_combat = false
	_detalhes.leaving_combat = false

	_detalhes:OnCombatPhaseChanged()
	_table_wipe(_detalhes.tabela_vigente.PhaseData.damage_section)
	_table_wipe(_detalhes.tabela_vigente.PhaseData.heal_section)

	_table_wipe(_detalhes.cache_damage_group)
	_table_wipe(_detalhes.cache_healing_group)

	_detalhes:UpdateParserGears()

	--> hide / alpha in combat
	for index, instancia in ipairs(_detalhes.tabela_instancias) do
		if instancia.ativa then
			--instancia:SetCombatAlpha(nil, nil, true) --passado para o regen enabled
			if instancia.auto_switch_to_old then
				instancia:CheckSwitchOnCombatEnd()
			end
		end
	end

	_detalhes.pre_pot_used = nil

	-- TODO
--	if _detalhes.encounter_table and _detalhes.encounter_table.id ~= 36597 then
		_table_wipe(_detalhes.encounter_table)
--	else
--		if _detalhes.debug then
--			_detalhes:Msg("(debug) in the lich king encounter, cannot wipe the encounter table.")
--		end
--	end

	_detalhes:InstanceCall(_detalhes.CheckPsUpdate)

	if invalid_combat then
		_detalhes:SendEvent("COMBAT_INVALID")
		_detalhes:SendEvent("COMBAT_PLAYER_LEAVE", nil, invalid_combat)
	else
		_detalhes:SendEvent("COMBAT_PLAYER_LEAVE", nil, _detalhes.tabela_vigente)
	end

	_detalhes:CheckForTextTimeCounter()
	_detalhes.StoreSpells()
	_detalhes:RunScheduledEventsAfterCombat()
end

-- TEMP
function _detalhes:GetPlayersInArena()
	local aliados = GetNumGroupMembers() -- LE_PARTY_CATEGORY_HOME
	for i = 1, aliados-1 do
		local role = UnitGroupRolesAssigned("party"..i)
		if role ~= "NONE" then
			local name = GetUnitName("party"..i, true)
			_detalhes.arena_table[name] = {role = role}
		end
	end

	local role = UnitGroupRolesAssigned("player")
	if role ~= "NONE" then
		local name = GetUnitName("player", true)
		_detalhes.arena_table[name] = {role = role}
	end

	if _detalhes.debug then
		_detalhes:Msg("(debug) Found", oponentes, "enemies and", aliados, "allies")
	end
end

local string_arena_enemyteam_damage = [[
	local combat = _detalhes:GetCombat("current")
	local total = 0

	for _, actor in combat[1]:ListActors() do
		if actor.arena_enemy then
			total = total + actor.total
		end
	end

	return total
]]

local string_arena_myteam_damage = [[
	local combat = _detalhes:GetCombat("current")
	local total = 0

	for _, actor in combat[1]:ListActors() do
		if actor.arena_ally then
			total = total + actor.total
		end
	end

	return total
]]

local string_arena_enemyteam_heal = [[
	local combat = _detalhes:GetCombat("current")
	local total = 0

	for _, actor in combat[2]:ListActors() do
		if actor.arena_enemy then
			total = total + actor.total
		end
	end

	return total
]]

local string_arena_myteam_heal = [[
	local combat = _detalhes:GetCombat("current")
	local total = 0

	for _, actor in combat[2]:ListActors() do
		if actor.arena_ally then
			total = total + actor.total
		end
	end

	return total
]]

function _detalhes:CreateArenaSegment()
	_detalhes:GetPlayersInArena()

	_detalhes.arena_begun = true
	_detalhes.start_arena = nil

	if _detalhes.in_combat then
		_detalhes:SairDoCombate()
	end

	--> registra os gr�ficos
	_detalhes:TimeDataRegister("Your Team Damage", string_arena_myteam_damage, nil, "Details!", "v1.0",[[Interface\ICONS\Ability_DualWield]], true, true)
	_detalhes:TimeDataRegister("Enemy Team Damage", string_arena_enemyteam_damage, nil, "Details!", "v1.0",[[Interface\ICONS\Ability_DualWield]], true, true)

	_detalhes:TimeDataRegister("Your Team Healing", string_arena_myteam_heal, nil, "Details!", "v1.0",[[Interface\ICONS\Ability_DualWield]], true, true)
	_detalhes:TimeDataRegister("Enemy Team Healing", string_arena_enemyteam_heal, nil, "Details!", "v1.0",[[Interface\ICONS\Ability_DualWield]], true, true)

	--> inicia um novo combate
	_detalhes:EntrarEmCombate()

	--> sinaliza que esse combate � arena
	_detalhes.tabela_vigente.arena = true
	_detalhes.tabela_vigente.is_arena = {name = _detalhes.zone_name, zone = _detalhes.zone_name, mapid = _detalhes.zone_id}

	_detalhes:SendEvent("COMBAT_ARENA_START")
end

function _detalhes:StartArenaSegment(...)
	if _detalhes.debug then
		_detalhes:Msg("(debug) starting a new arena segment.")
	end

	local timerType, timeSeconds, totalTime = ...

	if _detalhes.start_arena then
		_detalhes:CancelTimer(_detalhes.start_arena, true)
	end

	_detalhes.start_arena = _detalhes:ScheduleTimer("CreateArenaSegment", timeSeconds)
	_detalhes:GetPlayersInArena()
end

function _detalhes:EnteredInArena()
	if _detalhes.debug then
		_detalhes:Msg("(debug) the player EnteredInArena().")
	end

	_detalhes.arena_begun = false

	_detalhes:GetPlayersInArena()
end

function _detalhes:LeftArena()
	if _detalhes.debug then
		_detalhes:Msg("(debug) player LeftArena().")
	end

	_detalhes.is_in_arena = false
	_detalhes.arena_begun = false

	if _detalhes.start_arena then
		_detalhes:CancelTimer(_detalhes.start_arena, true)
	end

	_detalhes:TimeDataUnregister("Your Team Damage")
	_detalhes:TimeDataUnregister("Enemy Team Damage")

	_detalhes:TimeDataUnregister("Your Team Healing")
	_detalhes:TimeDataUnregister("Enemy Team Healing")

	_detalhes:SendEvent("COMBAT_ARENA_END")
end

-- TEMP
local validSpells = {
	[220893] = {class = "ROGUE", spec = 261, maxPercent = 0.075, container = 1, commID = "MISSDATA_ROGUE_SOULRIP"},
	--[11366] = {class = "MAGE", spec = 63, maxPercent = 0.9, container = 1, commID = "MISSDATA_ROGUE_SOULRIP"},
}
function _detalhes:CanSendMissData()
	if(not IsInRaid() and not IsInGroup()) then
		return
	end
	local _, playerClass = UnitClass("player")
	local specIndex = DetailsFramework.GetSpecialization()
	local playerSpecID
	if(specIndex) then
		playerSpecID = DetailsFramework.GetSpecializationInfo(specIndex)
	end

	if(playerSpecID and playerClass) then
		for spellID, t in pairs(validSpells) do
			if(playerClass == t.class and playerSpecID == t.spec) then
				_detalhes:SendMissData(spellID, t.container, _detalhes.network.ids[t.commID])
			end
		end
	end
	return false
end

function _detalhes:SendMissData(spellID, containerType, commID)
	local combat = _detalhes.tabela_vigente
	if combat then
		local damageActor = combat(containerType, _detalhes.playername)
		if damageActor then
			local spell = damageActor.spells:GetSpell(spellID)
			if spell then
				local data = {
					[1] = containerType,
					[2] = spellID,
					[3] = spell.total,
					[4] = spell.counter
				}

				if _detalhes.debug then
					_detalhes:Msg("(debug) sending miss data packet:", spellID, containerType, commID)
				end

				_detalhes:SendRaidOrPartyData(commID, data)
			end
		end
	end
end

function _detalhes.HandleMissData(playerName, data)
	local combat = _detalhes.tabela_vigente

	if _detalhes.debug then
		_detalhes:Msg("(debug) miss data received from:", playerName, "spellID:", data[2], data[3], data[4])
	end

	if combat then
		local containerType = data[1]
		if type(containerType) ~= "number" or containerType < 1 or containerType > 4 then
			return
		end

		local damageActor = combat(containerType, playerName)
		if damageActor then
			local spellID = data[2] --a spellID has been passed?
			if not spellID or type(spellID) ~= "number" then
				return
			end

			local validateSpell = validSpells[spellID]
			if not validateSpell then --is a valid spell?
				return
			end

			--does the target player fit in the spell requirement on OUR end?
			local class, spec, maxPercent = validateSpell.class, validateSpell.spec, validateSpell.maxPercent
			if class ~= damageActor.classe or spec ~= damageActor.spec then
				return
			end

			local total, counter = data[3], data[4]
			if type(total) ~= "number" or type(counter) ~= "number" then
				return
			end

			if total > (damageActor.total * maxPercent) then
				return
			end

			local spellObject = damageActor.spells:PegaHabilidade(spellID, true)
			if spellObject then
				if spellObject.total < total and total > 0 and damageActor.nome ~= _detalhes.playername then
					local difference = total - spellObject.total
					if difference > 0 then
						spellObject.total = total
						spellObject.counter = counter
						damageActor.total = damageActor.total + difference

						combat[containerType].need_refresh = true

						if _detalhes.debug then
							_detalhes:Msg("(debug) miss data successful added from:", playerName, data[2], "difference:", difference)
						end
					end
				end
			end
		end
	end
end

function _detalhes:MakeEqualizeOnActor(player, realm, receivedActor)
	if true then --> disabled for testing
		return
	end

	local combat = _detalhes:GetCombat("current")
	local damage, heal, energy, misc = _detalhes:GetAllActors("current", player)

	if not damage and not heal and not energy and not misc then
		--> try adding server name
		damage, heal, energy, misc = _detalhes:GetAllActors("current", player.."-"..realm)

		if not damage and not heal and not energy and not misc then
			--> not found any actor object, so we need to create
			local actorName

			if realm ~= GetRealmName() then
				actorName = player.."-"..realm
			else
				actorName = player
			end

			local guid = _detalhes:FindGUIDFromName(player)

			-- 0x512 normal party
			-- 0x514 normal raid

			if guid then
				damage = combat[1]:PegarCombatente(guid, actorName, 0x514, true)
				heal = combat[2]:PegarCombatente(guid, actorName, 0x514, true)
				energy = combat[3]:PegarCombatente(guid, actorName, 0x514, true)
				misc = combat[4]:PegarCombatente(guid, actorName, 0x514, true)

				if _detalhes.debug then
					_detalhes:Msg("(debug) equalize received actor:", actorName, damage, heal)
				end
			else
				if _detalhes.debug then
					_detalhes:Msg("(debug) equalize couldn't get guid for player ",player)
				end
			end
		end
	end

	combat[1].need_refresh = true
	combat[2].need_refresh = true
	combat[3].need_refresh = true
	combat[4].need_refresh = true

	if damage then
		if damage.total < receivedActor[1][1] then
			if _detalhes.debug then
				_detalhes:Msg(player.." damage before: "..damage.total.." damage received: "..receivedActor[1][1])
			end

			damage.total = receivedActor[1][1]
		end

		if damage.damage_taken < receivedActor[1][2] then
			damage.damage_taken = receivedActor[1][2]
		end

		if damage.friendlyfire_total < receivedActor[1][3] then
			damage.friendlyfire_total = receivedActor[1][3]
		end
	end

	if heal then
		if heal.total < receivedActor[2][1] then
			heal.total = receivedActor[2][1]
		end

		if heal.totalover < receivedActor[2][2] then
			heal.totalover = receivedActor[2][2]
		end

		if heal.healing_taken < receivedActor[2][3] then
			heal.healing_taken = receivedActor[2][3]
		end
	end

	if energy then
		if energy.mana and(receivedActor[3][1] > 0 and energy.mana < receivedActor[3][1]) then
			energy.mana = receivedActor[3][1]
		end

		if energy.e_rage and(receivedActor[3][2] > 0 and energy.e_rage < receivedActor[3][2]) then
			energy.e_rage = receivedActor[3][2]
		end

		if energy.e_energy and(receivedActor[3][3] > 0 and energy.e_energy < receivedActor[3][3]) then
			energy.e_energy = receivedActor[3][3]
		end

		if energy.runepower and(receivedActor[3][4] > 0 and energy.runepower < receivedActor[3][4]) then
			energy.runepower = receivedActor[3][4]
		end
	end

	if misc then
		if misc.interrupt and(receivedActor[4][1] > 0 and misc.interrupt < receivedActor[4][1]) then
			misc.interrupt = receivedActor[4][1]
		end

		if misc.dispell and(receivedActor[4][2] > 0 and misc.dispell < receivedActor[4][2]) then
			misc.dispell = receivedActor[4][2]
		end
	end
end

function _detalhes:EqualizePets()
	--> check for pets without owner
	for _, actor in _ipairs(_detalhes.tabela_vigente[1]._ActorTable) do
		--> have flag and the flag tell us he is a pet
		if actor.flag_original and bit.band(actor.flag_original, OBJECT_TYPE_PETS) ~= 0 then
			--> do not have owner and he isn't on owner container
			if not actor.owner and not _detalhes.tabela_pets.pets[actor.serial] then
				_detalhes:SendPetOwnerRequest(actor.serial, actor.nome)
			end
		end
	end
end

function _detalhes:EqualizeActorsSchedule(host_of)
	--> store pets sent through 'needpetowner'
	_detalhes.sent_pets = _detalhes.sent_pets or {n = time()}

	if _detalhes.sent_pets.n + 20 < time() then
		_table_wipe(_detalhes.sent_pets)
		_detalhes.sent_pets.n = time()
	end

	--> pet equilize disabled on details 1.4.0
--	_detalhes:ScheduleTimer("EqualizePets", 1 + math.random())

	--> do not equilize if there is any disabled capture
--	if _detalhes:CaptureIsAllEnabled() then
		_detalhes:ScheduleTimer("EqualizeActors", 2 + math.random() + math.random() , host_of)
--	end
end

function _detalhes:EqualizeActors(host_of)
	--> Disabling the sync. Since WoD combatlog are sent between player on phased zones during encounters.
	if not host_of or true then --> full disabled for testing
		return
	end

	if _detalhes.debug then
		_detalhes:Msg("(debug) sending equilize actor data")
	end

	local damage, heal, energy, misc

	if host_of then
		damage, heal, energy, misc = _detalhes:GetAllActors("current", host_of)
	else
		damage, heal, energy, misc = _detalhes:GetAllActors("current", _detalhes.playername)
	end

	if damage then
		damage = {damage.total or 0, damage.damage_taken or 0, damage.friendlyfire_total or 0}
	else
		damage = {0, 0, 0}
	end

	if heal then
		heal = {heal.total or 0, heal.totalover or 0, heal.healing_taken or 0}
	else
		heal = {0, 0, 0}
	end

	if energy then
		energy = {energy.mana or 0, energy.e_rage or 0, energy.e_energy or 0, energy.runepower or 0}
	else
		energy = {0, 0, 0, 0}
	end

	if misc then
		misc = {misc.interrupt or 0, misc.dispell or 0}
	else
		misc = {0, 0}
	end

	local data = {damage, heal, energy, misc}

	--> envia os dados do proprio host pra ele antes
	if host_of then
		_detalhes:SendRaidDataAs(_detalhes.network.ids.CLOUD_EQUALIZE, host_of, nil, data)
		_detalhes:EqualizeActors()
	else
		_detalhes:SendRaidData(_detalhes.network.ids.CLOUD_EQUALIZE, data)
	end
end

function _detalhes:FlagActorsOnPvPCombat()
	for class_type, container in _ipairs(_detalhes.tabela_vigente) do
		for _, actor in _ipairs(container._ActorTable) do
			actor.pvp_component = true
		end
	end
end

function _detalhes:FlagActorsOnBossFight()
	for class_type, container in _ipairs(_detalhes.tabela_vigente) do
		for _, actor in _ipairs(container._ActorTable) do
			actor.boss_fight_component = true
		end
	end
end

local fight_component = function(energy_container, misc_container, name)
	local on_energy = energy_container._ActorTable[energy_container._NameIndexTable[name]]
	if on_energy then
		on_energy.fight_component = true
	end
	local on_misc = misc_container._ActorTable[misc_container._NameIndexTable[name]]
	if on_misc then
		on_misc.fight_component = true
	end
end

function _detalhes:FlagActorsOnCommonFight()
	local damage_container = _detalhes.tabela_vigente[1]
	local healing_container = _detalhes.tabela_vigente[2]
	local energy_container = _detalhes.tabela_vigente[3]
	local misc_container = _detalhes.tabela_vigente[4]

	local mythicDungeonRun = _detalhes.tabela_vigente.is_mythic_dungeon_segment

	for class_type, container in _ipairs({damage_container, healing_container}) do
		for _, actor in _ipairs(container._ActorTable) do
			if mythicDungeonRun then
				actor.fight_component = true
			end

			if actor.grupo then
				if class_type == 1 or class_type == 2 then
					for target_name, amount in _pairs(actor.targets) do
						local target_object = container._ActorTable[container._NameIndexTable[target_name]]
						if target_object then
							target_object.fight_component = true
							fight_component(energy_container, misc_container, target_name)
						end
					end
					if class_type == 1 then
						for damager_actor, _ in _pairs(actor.damage_from) do
							local target_object = container._ActorTable[container._NameIndexTable[damager_actor]]
							if target_object then
								target_object.fight_component = true
								fight_component(energy_container, misc_container, damager_actor)
							end
						end
					elseif class_type == 2 then
						for healer_actor, _ in _pairs(actor.healing_from) do
							local target_object = container._ActorTable[container._NameIndexTable[healer_actor]]
							if target_object then
								target_object.fight_component = true
								fight_component(energy_container, misc_container, healer_actor)
							end
						end
					end
				end
			end
		end
	end
end

function _detalhes:AtualizarJanela(instancia, _segmento)
	if _segmento then --> apenas atualizar janelas que estejam mostrando o segmento solicitado
		if _segmento == instancia.segmento then
			instancia:TrocaTabela(instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true)
		end
	else
		if instancia.modo == modo_GROUP or instancia.modo == modo_ALL then
			instancia:TrocaTabela(instancia, instancia.segmento, instancia.atributo, instancia.sub_atributo, true)
		end
	end
end

function _detalhes:PostponeInstanceToCurrent(instance)
	if not instance.last_interaction or (instance.ativa and (instance.last_interaction + 3 < _tempo) and (not DetailsReportWindow or not DetailsReportWindow:IsShown()) and (not _detalhes.janela_info:IsShown())) then
		instance._postponing_current = nil
		if instance.segmento == 0 then
			return _detalhes:TrocaSegmentoAtual(instance)
		else
			return
		end
	end

	if instance.is_interacting and instance.last_interaction < _tempo then
		instance.last_interaction = _tempo
	end

	instance._postponing_current = _detalhes:ScheduleTimer("PostponeInstanceToCurrent", 1, instance)
end

function _detalhes:TrocaSegmentoAtual(instancia, is_encounter)
	if instancia.segmento == 0 and instancia.baseframe and instancia.ativa then
		if not is_encounter then
			if instancia.is_interacting then
				if not instancia.last_interaction or instancia.last_interaction < _tempo then
					instancia.last_interaction = _tempo or time()
				end
			end

			if (instancia.last_interaction and (instancia.last_interaction + 3 > _detalhes._tempo)) or (DetailsReportWindow and DetailsReportWindow:IsShown()) or (_detalhes.janela_info:IsShown()) then
				--> postpone
				instancia._postponing_current = _detalhes:ScheduleTimer("PostponeInstanceToCurrent", 1, instancia)
				return
			end
		end

		--print("==> Changing the Segment now! - control.lua 1220")

		instancia.last_interaction = _tempo - 4 --pode setar, completou o ciclo
		instancia._postponing_current = nil
		instancia.showing = _detalhes.tabela_vigente
		instancia:ResetaGump()
		_detalhes.gump:Fade(instancia, "in", nil, "barras")
	end
end

function _detalhes:SetTrashSuppression(n)
	assert(type(n) == "number", "SetTrashSuppression expects a number on index 1.")

	if n < 0 then
		n = 0
	end

	_detalhes.instances_suppress_trash = n
end

function _detalhes:CheckFor_SuppressedWindowsOnEncounterFound()
	for _, instance in _detalhes:ListInstances() do
		if instance.ativa and instance.baseframe and (not instance.last_interaction or instance.last_interaction > _tempo) and instance.segmento == 0 then
			_detalhes:TrocaSegmentoAtual(instance, true)
		end
	end
end

function _detalhes:CheckFor_EnabledTrashSuppression()
	if _detalhes.HasTrashSuppression and _detalhes.HasTrashSuppression > _tempo then
		self.last_interaction = _detalhes.HasTrashSuppression
	end
end

function _detalhes:SetTrashSuppressionAfterEncounter()
	_detalhes:InstanceCall("CheckFor_EnabledTrashSuppression")
end

function _detalhes:CheckFor_TrashSuppressionOnEncounterEnd()
	if _detalhes.instances_suppress_trash > 0 then
		_detalhes.HasTrashSuppression = _tempo + _detalhes.instances_suppress_trash
		--> delaying in 3 seconds for other stuff like auto open windows after combat.
		_detalhes:ScheduleTimer("SetTrashSuppressionAfterEncounter", 3)
	end
end

--> internal GetCombatId() version
function _detalhes:NumeroCombate(flag)
	if flag == 0 then
		_detalhes.combat_id = 0
	elseif flag then
		_detalhes.combat_id = _detalhes.combat_id + flag
	end
	return _detalhes.combat_id
end

--> tooltip fork / search key: ~tooltip
local avatarPoint = {"bottomleft", "topleft", -3, -4}
local backgroundPoint = {{"bottomleft", "topleft", 0, -3}, {"bottomright", "topright", 0, -3}}
local textPoint = {"left", "right", -11, -5}
local avatarTexCoord = {0, 1, 0, 1}
local backgroundColor = {0, 0, 0, 0.6}
local avatarTextColor = {1, 1, 1, 1}

function _detalhes:AddTooltipReportLineText()
	GameCooltip:AddLine(Loc["STRING_CLICK_REPORT_LINE1"], Loc["STRING_CLICK_REPORT_LINE2"])
	GameCooltip:AddStatusBar(100, 1, 0, 0, 0, 0.8)
end

function _detalhes:AddTooltipBackgroundStatusbar(side, value, useSpark)
	_detalhes.tooltip.background[4] = 0.8
	_detalhes.tooltip.icon_size.W = _detalhes.tooltip.line_height
	_detalhes.tooltip.icon_size.H = _detalhes.tooltip.line_height

	value = value or 100

	if(not side) then
		local r, g, b, a = unpack(_detalhes.tooltip.background)
		GameCooltip:AddStatusBar(value, 1, r, g, b, a, useSpark, {value = 100, color = {.21, .21, .21, 0.8}, texture =[[Interface\AddOns\Details\images\bar_serenity]]})

	else
		GameCooltip:AddStatusBar(value, 2, unpack(_detalhes.tooltip.background))
	end
end

function _detalhes:AddTooltipHeaderStatusbar(r, g, b, a)
	local r, g, b, a, statusbarGlow, backgroundBar = unpack(_detalhes.tooltip.header_statusbar)
	GameCooltip:AddStatusBar(100, 1, r, g, b, a, statusbarGlow, backgroundBar, "Skyline")
end

-- /run local a,b=_detalhes.tooltip.header_statusbar,0.3;a[1]=b;a[2]=b;a[3]=b;a[4]=0.8;

function _detalhes:AddTooltipSpellHeaderText(headerText, headerColor, amount, iconTexture, L, R, T, B)
	if _detalhes.tooltip.show_amount then
		GameCooltip:AddLine(headerText, "x" .. amount .. "", nil, headerColor, 1, 1, 1, .4, _detalhes.tooltip.fontsize_title)
	else
		GameCooltip:AddLine(headerText, nil, nil, headerColor, nil, _detalhes.tooltip.fontsize_title)
	end

	if iconTexture then
		GameCooltip:AddIcon(iconTexture, 1, 1, 14, 14, L or 0, R or 1, T or 0, B or 1)
	end
end

local bgColor, borderColor = {0, 0, 0, 0.8}, {0, 0, 0, 0} --{0.37, 0.37, 0.37, .75}, {.30, .30, .30, .3}

function _detalhes:BuildInstanceBarTooltip(frame)
	local GameCooltip = GameCooltip

	GameCooltip:Reset()
	GameCooltip:SetType("tooltip")

	GameCooltip:SetOption("MinWidth", _math_max(230, self.baseframe:GetWidth()*0.98))
	GameCooltip:SetOption("StatusBarTexture",[[Interface\AddOns\Details\images\bar_background]])

	GameCooltip:SetOption("TextSize", _detalhes.tooltip.fontsize)
	GameCooltip:SetOption("TextFont",  _detalhes.tooltip.fontface)
	GameCooltip:SetOption("TextColor", _detalhes.tooltip.fontcolor)
	GameCooltip:SetOption("TextColorRight", _detalhes.tooltip.fontcolor_right)
	GameCooltip:SetOption("TextShadow", _detalhes.tooltip.fontshadow and "OUTLINE")

	GameCooltip:SetOption("LeftBorderSize", -4)
	GameCooltip:SetOption("RightBorderSize", 4)
	GameCooltip:SetOption("RightTextMargin", 0)
	GameCooltip:SetOption("VerticalOffset", 8)
	GameCooltip:SetOption("AlignAsBlizzTooltip", true)
	GameCooltip:SetOption("AlignAsBlizzTooltipFrameHeightOffset", -8)
	GameCooltip:SetOption("LineHeightSizeOffset", 4)
	GameCooltip:SetOption("VerticalPadding", -4)

	GameCooltip:SetBackdrop(1, _detalhes.cooltip_preset2_backdrop, bgColor, borderColor)

	local myPoint = _detalhes.tooltip.anchor_point
	local anchorPoint = _detalhes.tooltip.anchor_relative
	local x_Offset = _detalhes.tooltip.anchor_offset[1]
	local y_Offset = _detalhes.tooltip.anchor_offset[2]

	if _detalhes.tooltip.anchored_to == 1 then
		GameCooltip:SetHost(frame, myPoint, anchorPoint, x_Offset, y_Offset)
	else
		GameCooltip:SetHost(DetailsTooltipAnchor, myPoint, anchorPoint, x_Offset, y_Offset)
	end
end

function _detalhes:MontaTooltip(frame, qual_barra, keydown)
	self:BuildInstanceBarTooltip(frame)

	local GameCooltip = GameCooltip

	local esta_barra = self.barras[qual_barra] --> barra que o mouse passou em cima e ir� mostrar o tooltip
	local objeto = esta_barra.minha_tabela --> pega a referencia da tabela --> retorna a classe_damage ou classe_heal
	if not objeto then --> a barra n�o possui um objeto
		return false
	end

	--verifica por tooltips especiais:
	if objeto.dead then --> � uma barra de dead
		return _detalhes:ToolTipDead(self, objeto, esta_barra, keydown) --> inst�ncia,[morte], barra
	elseif objeto.byspell then
		return _detalhes:ToolTipBySpell(self, objeto, esta_barra, keydown)
	elseif objeto.frags then
		return _detalhes:ToolTipFrags(self, objeto, esta_barra, keydown)
	elseif objeto.boss_debuff then
		return _detalhes:ToolTipVoidZones(self, objeto, esta_barra, keydown)
	end

	local t = objeto:ToolTip(self, qual_barra, esta_barra, keydown) --> inst�ncia, n� barra, objeto barra, keydown
	if t then
		if objeto.serial and objeto.serial ~= "" then
			local avatar = NickTag:GetNicknameTable(objeto.serial, true)
			if avatar and not _detalhes.ignore_nicktag then
				if avatar[2] and avatar[4] and avatar[1] then
					GameCooltip:SetBannerImage(1, avatar[2], 80, 40, avatarPoint, avatarTexCoord, nil) --> overlay[2] avatar path
					GameCooltip:SetBannerImage(2, avatar[4], 200, 55, backgroundPoint, avatar[5], avatar[6]) --> background
					GameCooltip:SetBannerText(1, (not _detalhes.ignore_nicktag and avatar[1]) or objeto.nome, textPoint, avatarTextColor, 14, SharedMedia:Fetch("font", _detalhes.tooltip.fontface)) --> text[1] nickname
				end
			else
--				if _detalhes.remove_realm_from_name and objeto.displayName:find("%*") then
--					GameCooltip:SetBannerImage(1,[[Interface\AddOns\Details\images\background]], 20, 30, avatarPoint, avatarTexCoord, {0, 0, 0, 0}) --> overlay[2] avatar path
--					GameCooltip:SetBannerImage(2,[[Interface\PetBattles\Weather-BurntEarth]], 160, 30, {{"bottomleft", "topleft", 0, -5}, {"bottomright", "topright", 0, -5}}, {0.12, 0.88, 1, 0}, {0, 0, 0, 0.1}) --> overlay[2] avatar path {0, 0, 0, 0}
--					GameCooltip:SetBannerText(1, objeto.nome, {"left", "left", 11, -8}, {1, 1, 1, 0.7}, 10, SharedMedia:Fetch("font", _detalhes.tooltip.fontface)) --> text[1] nickname
--				end
			end
		end

		GameCooltip:ShowCooltip()
	end
end

function _detalhes.gump:UpdateTooltip(qual_barra, esta_barra, instancia)
	if _IsShiftKeyDown() then
		return instancia:MontaTooltip(esta_barra, qual_barra, "shift")
	elseif _IsControlKeyDown() then
		return instancia:MontaTooltip(esta_barra, qual_barra, "ctrl")
	elseif _IsAltKeyDown() then
		return instancia:MontaTooltip(esta_barra, qual_barra, "alt")
	else
		return instancia:MontaTooltip(esta_barra, qual_barra)
	end
end

function _detalhes:EndRefresh(instancia, total, tabela_do_combate, showing)
	_detalhes:EsconderBarrasNaoUsadas(instancia, showing)
end

function _detalhes:EsconderBarrasNaoUsadas(instancia, showing)
	--> primeira atualiza��o ap�s uma mudan�a de segmento -->  verifica se h� mais barras sendo mostradas do que o necess�rio
	--------------------
	if instancia.v_barras then
		--print("mostrando", instancia.rows_showing, instancia.rows_created)
		for barra_numero = instancia.rows_showing+1, instancia.rows_created do
			_detalhes.gump:Fade(instancia.barras[barra_numero], "in")
		end
		instancia.v_barras = false

		if instancia.rows_showing == 0 and instancia:GetSegment() == -1 then -- -1 overall data
			if not instancia:IsShowingOverallDataWarning() then
				local tutorial = _detalhes:GetTutorialCVar("OVERALLDATA_WARNING1") or 0
				if (type(tutorial) == "number") and(tutorial < 60) then
					_detalhes:SetTutorialCVar("OVERALLDATA_WARNING1", tutorial + 1)
					instancia:ShowOverallDataWarning(true)
				end
			end
		else
			if instancia:IsShowingOverallDataWarning() then
				instancia:ShowOverallDataWarning(false)
			end
		end
	end

	return showing
end

--> call update functions
function _detalhes:AtualizarALL(forcar)
	local tabela_do_combate = self.showing

	--> confere se a inst�ncia possui uma tabela v�lida
	if not tabela_do_combate then
		if not self.freezed then
			return self:Freeze()
		end
		return
	end

	local need_refresh = tabela_do_combate[self.atributo].need_refresh
	if not need_refresh and not forcar then
		return --> n�o precisa de refresh
--	else
--		tabela_do_combate[self.atributo].need_refresh = false
	end

	if self.atributo == 1 then --> damage
		return atributo_damage:RefreshWindow(self, tabela_do_combate, forcar, nil, need_refresh)
	elseif self.atributo == 2 then --> heal
		return atributo_heal:RefreshWindow(self, tabela_do_combate, forcar, nil, need_refresh)
	elseif self.atributo == 3 then --> energy
		return atributo_energy:RefreshWindow(self, tabela_do_combate, forcar, nil, need_refresh)
	elseif self.atributo == 4 then --> outros
		return atributo_misc:RefreshWindow(self, tabela_do_combate, forcar, nil, need_refresh)
	elseif self.atributo == 5 then --> ocustom
		return atributo_custom:RefreshWindow(self, tabela_do_combate, forcar, nil, need_refresh)
	end
end

function _detalhes:ForceRefresh()
	self:AtualizaGumpPrincipal(true)
end

function _detalhes:AtualizaGumpPrincipal(instancia, forcar)
	if not instancia or type(instancia) == "boolean" then --> o primeiro par�metro n�o foi uma inst�ncia ou ALL
		forcar = instancia
		instancia = self
	end

	if not forcar then
		_detalhes.LastUpdateTick = _detalhes._tempo
	end

	if instancia == -1 then
		--> update
		for index, esta_instancia in _ipairs(_detalhes.tabela_instancias) do
			if esta_instancia.ativa then
				if esta_instancia.modo == modo_GROUP or esta_instancia.modo == modo_ALL then
					esta_instancia:AtualizarALL(forcar)
				end
			end
		end

		--> marcar que n�o precisa ser atualizada
		for index, esta_instancia in _ipairs(_detalhes.tabela_instancias) do
			if esta_instancia.ativa and esta_instancia.showing then
				if esta_instancia.modo == modo_GROUP or esta_instancia.modo == modo_ALL then
					if esta_instancia.atributo <= 4 then
						esta_instancia.showing[esta_instancia.atributo].need_refresh = false
					end
				end
			end
		end

		if not forcar then --atualizar o gump de detalhes tamb�m se ele estiver aberto
			if info.ativo then
				return info.jogador:MontaInfo()
			end
		end

		return
	else
		if not instancia.ativa then
			return
		end
	end

	if instancia.modo == modo_ALL or instancia.modo == modo_GROUP then
		return instancia:AtualizarALL(forcar)
	end
end

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
--> core

function _detalhes:AutoEraseConfirm()
	local panel = DetailsEraseDataConfirmation
	if not panel then
		panel = CreateFrame("Frame", "DetailsEraseDataConfirmation", UIParent)
		panel:SetSize(400, 85)
		panel:SetBackdrop({
			bgFile =[[Interface\AddOns\Details\images\background]], tile = true, tileSize = 16,
			edgeFile =[[Interface\AddOns\Details\images\border_2]], edgeSize = 12
		})
		panel:SetPoint("CENTER", UIParent)
		panel:SetBackdropColor(0, 0, 0, 0.4)

		panel:SetScript("OnMouseDown", function(self, button)
			if button == "RightButton" then
				panel:Hide()
			end
		end)

		--local icon = _detalhes.gump:CreateImage(panel,[[Interface\AddOns\Details\images\logotipo]], 512*0.4, 256*0.4)
		--icon:SetPoint("BOTTOMLEFT", panel, "TOPLEFT", -10, -11)

		local text = _detalhes.gump:CreateLabel(panel, Loc["STRING_OPTIONS_CONFIRM_ERASE"], nil, nil, "GameFontNormal")
		text:SetPoint("CENTER", panel, "CENTER")
		text:SetPoint("TOP", panel, "TOP", 0, -10)

		local no = _detalhes.gump:CreateButton(panel, function() panel:Hide() end, 90, 20, Loc["STRING_NO"])
		no:SetPoint("BOTTOMLEFT", panel, "BOTTOMLEFT", 30, 10)
		no:InstallCustomTexture(nil, nil, nil, nil, true)

		local yes = _detalhes.gump:CreateButton(panel, function() panel:Hide(); _detalhes.tabela_historico:resetar() end, 90, 20, Loc["STRING_YES"])
		yes:SetPoint("BOTTOMRIGHT", panel, "BOTTOMRIGHT", -30, 10)
		yes:InstallCustomTexture(nil, nil, nil, nil, true)
	end

	panel:Show()
end

function _detalhes:CheckForAutoErase(mapid)
	if _detalhes.last_instance_id ~= mapid then
		_detalhes.tabela_historico:resetar_overall()

		if _detalhes.segments_auto_erase == 2 then
			--ask
			_detalhes:ScheduleTimer("AutoEraseConfirm", 1)
		elseif _detalhes.segments_auto_erase == 3 then
			--erase
			_detalhes.tabela_historico:resetar()
		end
	else
		if _tempo > _detalhes.last_instance_time + 21600 then --6 hours
			if _detalhes.segments_auto_erase == 2 then
				--ask
				_detalhes:ScheduleTimer("AutoEraseConfirm", 1)
			elseif _detalhes.segments_auto_erase == 3 then
				--erase
				_detalhes.tabela_historico:resetar()
			end
		end
	end

	_detalhes.last_instance_id = mapid
	_detalhes.last_instance_time = _tempo
	--_detalhes.last_instance_time = 0 --debug
end

function _detalhes:UpdateControl()
	_tempo = _detalhes._tempo
end