-----------------------------------------------------------------------
-- AddOn namespace.
-----------------------------------------------------------------------
local ADDON_NAME, private = ...

local RSRespawnTracker = private.NewLib("RareScannerRespawnTracker")

-- RareScanner database libraries
local RSNpcDB = private.ImportLib("RareScannerNpcDB")
local RSContainerDB = private.ImportLib("RareScannerContainerDB")
local RSEventDB = private.ImportLib("RareScannerEventDB")

-- RareScanner internal libraries
local RSConstants = private.ImportLib("RareScannerConstants")
local RSLogger = private.ImportLib("RareScannerLogger")

-- Timers
local CHECK_RESPAWN_TIMER

---============================================================================
-- Tracks respawning
---============================================================================

local currentReCheckTickers = {
  npcs = {},
  containers = {},
  events = {}
}

local function ReCheckRespawnTimers()
  -- Check for the lists
	for npcID, info in pairs (currentReCheckTickers.npcs) do
  	if (C_QuestLog.IsQuestFlaggedCompleted(info.q)) then
  		if (info.n == 0) then
  			RSNpcDB.SetNpcKilled(npcID)
        currentReCheckTickers.npcs[npcID] = nil
        RSLogger:PrintDebugMessageEntityID(npcID, string.format("ReCheckRespawnTimers [NPC: %s]. Muerto para siempre!", npcID))
        RSLogger:PrintDebugMessageEntityID(npcID, string.format("- Quest [%s] asociada.", info.q))
  		else
  			currentReCheckTickers.npcs[npcID].n = (info.n - 1)
        RSLogger:PrintDebugMessageEntityID(npcID, string.format("ReCheckRespawnTimers [info.n: %s].", info.n))
  		end
  	-- Otherwise it has respawn
  	else
  		RSLogger:PrintDebugMessageEntityID(npcID, string.format("ReCheckRespawnTimers [NPC: %s]. Respawn!", npcID))
  		RSNpcDB.DeleteNpcKilled(npcID)
      currentReCheckTickers.npcs[npcID] = nil
  	end
  end
  
  for containerID, info in pairs (currentReCheckTickers.containers) do
		-- If it remains opened the container is not coming back
		if (C_QuestLog.IsQuestFlaggedCompleted(info.q)) then
			if (info.n == 0) then
				RSContainerDB.SetContainerOpened(containerID)
        currentReCheckTickers.containers[containerID] = nil
        RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [Contenedor: %s]. Abierto para siempre!", containerID))
        RSLogger:PrintDebugMessage(string.format("- Quest [%s] asociada.", info.q))
			else
				currentReCheckTickers.containers[containerID].n = (info.n - 1)
        RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [numOfTries: %s].", info.n))
			end
		-- Otherwise it has respawn
		else
			RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [Contenedor: %s]. Respawn!", containerID))
			RSContainerDB.DeleteContainerOpened(containerID)
      currentReCheckTickers.containers[containerID] = nil
		end
	end
  
  for eventID, info in pairs (currentReCheckTickers.events) do
		-- If it remains opened the container is not coming back
		if (C_QuestLog.IsQuestFlaggedCompleted(info.q)) then
			if (info.n == 0) then
				RSEventDB.SetEventCompleted(eventID)
        currentReCheckTickers.events[eventID] = nil
        RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [Evento: %s]. Completo para siempre!", eventID))
        RSLogger:PrintDebugMessage(string.format("- Quest [%s] asociada.", info.q))
			else
				currentReCheckTickers.containers[eventID].n = (info.n - 1)
        RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [numOfTries: %s].", info.n))
			end
		-- Otherwise it has respawn
		else
			RSLogger:PrintDebugMessage(string.format("ReCheckRespawnTimers [Evento: %s]. Respawn!", eventID))
			RSEventDB.DeleteEventCompleted(eventID)
			currentReCheckTickers[info.q] = nil
		end
	end
end

local function CheckRespawnTimers()
	-- Look for NPCs that have already respawn 
	for npcID, respawnTime in pairs (RSNpcDB.GetAllNpcsKilledRespawnTimes()) do
		if (respawnTime > 0 and respawnTime < time()) then
			-- If the associated quest is completed it means that this rare NPC is still dead
			-- It's possible that the quest takes a little bit longer to reset, so check for this NPC later
			local npcInfo = RSNpcDB.GetInternalNpcInfo(npcID)
			local hasRespawn = true
			if (npcInfo and npcInfo.questID and not npcInfo.reset and not npcInfo.questReset and not npcInfo.weeklyReset and not npcInfo.resetTimer) then  
				for _, questID in ipairs (npcInfo.questID) do
					if (C_QuestLog.IsQuestFlaggedCompleted(questID)) then
						-- Check this same NPC every 5 minutes during the next 15
            RSLogger:PrintDebugMessageEntityID(npcID, string.format("CheckRespawnTimers [NPC: %s], sigue muerto acorde a su quest [%s]", npcID, questID))
            if (not currentReCheckTickers.npcs[npcID]) then
              currentReCheckTickers.npcs[npcID] = { q = questID, n = 3 }
						end
						hasRespawn = false
						break
					end
				end
			end
			
			if (hasRespawn) then
        RSLogger:PrintDebugMessageEntityID(npcID, string.format("CheckRespawnTimers [NPC: %s]. Respawn!", npcID))
        RSNpcDB.DeleteNpcKilled(npcID)
      end
		end
	end
	
	-- Look for containers that have already respawn
	for containerID, respawnTime in pairs (RSContainerDB.GetAllContainersOpenedRespawnTimes()) do
		if (respawnTime > 0 and respawnTime < time()) then
			-- If the associated quest is completed it means that this container is still closed
			-- It's possible that the quest takes a little bit longer to reset, so check for this container later
			local containerInfo = RSContainerDB.GetInternalContainerInfo(containerID)
      local hasRespawn = true
			if (containerInfo and containerInfo.questID and not containerInfo.reset and not containerInfo.questReset and not containerInfo.weeklyReset and not containerInfo.resetTimer) then
				for _, questID in ipairs (containerInfo.questID) do
					if (C_QuestLog.IsQuestFlaggedCompleted(questID)) then
            RSLogger:PrintDebugMessage(string.format("CheckRespawnTimers [Contenedor: %s], sigue cerrado acorde a su quest [%s]", containerID, questID))
            if (not currentReCheckTickers.containers[containerID]) then
              currentReCheckTickers.containers[containerID] = { q = questID, n = 3 }
						end
            hasRespawn = false
						break
					end
				end
			end
			
      if (hasRespawn) then
        RSLogger:PrintDebugMessage(string.format("CheckRespawnTimers [Contenedor: %s]. Respawn!", containerID))
        RSContainerDB.DeleteContainerOpened(containerID)
      end
		end
	end
	
	-- Look for events that have already respawn
	for eventID, respawnTime in pairs (RSEventDB.GetAllEventsCompletedRespawnTimes()) do
		if (respawnTime > 0 and respawnTime < time()) then
			-- If the associated quest is completed it means that this event is still completed
			-- It's possible that the quest takes a little bit longer to reset, so check for this event later
			local eventInfo = RSEventDB.GetInternalEventInfo(eventID)
      local hasRespawn = true
			if (eventInfo and eventInfo.questID and not eventInfo.reset and not eventInfo.questReset and not eventInfo.weeklyReset and not eventInfo.resetTimer) then
				for _, questID in ipairs (eventInfo.questID) do
					if (C_QuestLog.IsQuestFlaggedCompleted(questID)) then
            RSLogger:PrintDebugMessage(string.format("CheckRespawnTimers [Evento: %s], sigue completo acorde a su quest [%s]", eventID, questID))
						-- Check this same event every 5 minutes during the next 15
						if (not currentReCheckTickers.events[eventID]) then
              currentReCheckTickers.containers[eventID] = { q = questID, n = 3 }
						end
            hasRespawn = false
						break
          end
				end
			end
			
      if (hasRespawn) then
        RSLogger:PrintDebugMessage(string.format("CheckRespawnTimers [Evento: %s]. Respawn!", eventID))
        RSEventDB.DeleteEventCompleted(eventID)
      end
		end
	end
end

function RSRespawnTracker.Init()
  if (not CHECK_RESPAWN_TIMER) then
    CheckRespawnTimers()
    
    CHECK_RESPAWN_TIMER = C_Timer.NewTicker(RSConstants.CHECK_RESPAWNING_BY_LASTSEEN_TIMER, function() 
      CheckRespawnTimers()
    end)
    
    C_Timer.NewTicker(RSConstants.CHECK_RESPAWN_BY_QUEST_TIMER, function() 
      ReCheckRespawnTimers()
    end)
  end
end