local profile = require("core.profile")
local CL = require("camera.CameraLibrary")
local UICALLS = require("ui.uicalls")
local kCombatRadius = 50
local SIDE_LEFT, SIDE_BOTTOMLEFT, SIDE_BOTTOMRIGHT, SIDE_RIGHT, SIDE_TOPRIGHT, SIDE_TOPLEFT = 1, 2, 3, 4, 5, 6
local MAX_SIDES = SIDE_TOPLEFT
local player = game.Player.FindPlayer()
local enemies
local gOffscreenSideData = {}
local GetSide = function(angle)
  local side
  if 0 < angle then
    if angle < 45 then
      side = SIDE_TOPRIGHT
    elseif angle < 135 then
      side = SIDE_RIGHT
    else
      side = SIDE_BOTTOMRIGHT
    end
  elseif -45 < angle then
    side = SIDE_TOPLEFT
  elseif -135 < angle then
    side = SIDE_LEFT
  else
    side = SIDE_BOTTOMLEFT
  end
  return side
end
local Init = function(gVFSAlternativeOffscreenIndicators)
  for i = 1, MAX_SIDES do
    local temp = {
      enemyCount = 0,
      attackerCount = 0,
      index = i,
      previousCount = 0,
      previousAttacker = 0,
      offscreenColorSetting = 1
    }
    if gVFSAlternativeOffscreenIndicators ~= nil then
      temp.offscreenColorSetting = gVFSAlternativeOffscreenIndicators.value
    end
    table.insert(gOffscreenSideData, temp)
  end
end
local ResetData = function()
  for i = 1, MAX_SIDES do
    gOffscreenSideData[i].enemyCount = 0
    gOffscreenSideData[i].attackerCount = 0
  end
end
local UpdateOffScreenIndicator = function()
  if game.Camera.GetPrimary() == nil then
    return
  end
  ResetData()
  local camPos = game.Camera.GetOrbitPosition()
  enemies = player:FindEnemies(kCombatRadius)
  local xzAngle
  for _, ai in pairs(enemies) do
    if not ai:IsDying() and not ai:IsDead() and not ai:HasMarker("nooffscreen") and ai:GetTargetCreature() == player then
      local pos = ai:GetWorldJointPosition(ai:GetJointIndex("JOPelvis1"))
      if not (0 < game.Camera.GetViewPenetration(pos, 0, 0)) then
        xzAngle = CL.FrontAngleXZ(pos)
        local side = GetSide(xzAngle)
        if side ~= SIDE_TOPRIGHT and side ~= SIDE_TOPLEFT or not (game.AIUtil.Distance(camPos, pos) < 20) then
          if ai:HasMarker("Attacking") then
            if side ~= nil then
              gOffscreenSideData[side].enemyCount = gOffscreenSideData[side].enemyCount + 1
              gOffscreenSideData[side].attackerCount = gOffscreenSideData[side].attackerCount + 1
            end
          elseif game.AIUtil.Distance(camPos, pos) < 12 and ai:IsInNavigationMove() then
            gOffscreenSideData[side].enemyCount = 0
          end
        end
      end
    end
  end
  if game.Level.GetVariable("DEBUFF_Disable_Offscreen_Indicators") then
    for i = 1, MAX_SIDES do
      gOffscreenSideData[i].enemyCount = 100
      gOffscreenSideData[i].attackerCount = 0
    end
  end
  local isDirty = false
  for side, _ in ipairs(gOffscreenSideData) do
    if gOffscreenSideData[side].previousCount ~= gOffscreenSideData[side].enemyCount or gOffscreenSideData[side].previousAttacker ~= gOffscreenSideData[side].attackerCount then
      isDirty = true
    end
    gOffscreenSideData[side].previousCount = gOffscreenSideData[side].enemyCount
    gOffscreenSideData[side].previousAttacker = gOffscreenSideData[side].attackerCount
  end
  if isDirty then
    UICALLS.UI_Event_Update_Offscreen_Indicators(gOffscreenSideData)
  end
end
return profile.WrapLibrary({Init = Init, UpdateOffScreenIndicator = UpdateOffScreenIndicator})
