local poilib = require("behavior.poi")
local player, son, son_bb, jointPos
local INIT_STATE, INACTIVE_SATE, CHECK_IN_VIEW_STATE, SON_USE_POI_STATE, READY_STATE = 0, 1, 2, 3, 4
local son_interact_state = INIT_STATE
local interactivePOIs
local MIN_PLAYER_DISTANCE = 30
local MIN_SON_DISTANCE = 45
local MIN_CAMERA_PERCENT = 0.65
local Init = function()
  print("son interact init")
  player = game.Player.FindPlayer()
  son = game.AI.FindSon()
  son_interact_state = INIT_STATE
  son_bb = son:GetPrivateBlackboard()
end
local GetCheckPosition = function(poi)
  local jointIndex
  local checkPos = poi:GetWorldPosition()
  if poi:FindJointIndex("promptJoint_Son") then
    jointIndex = poi:GetJointIndex("promptJoint_Son")
    checkPos = poi:GetWorldJointPosition(jointIndex)
  end
  return checkPos
end
local OnPlayerInput = function()
  return false
end
local CheckInteractRange = function(obj)
  local override_range = obj:FindLuaTableAttribute("KratosRange")
  local override_rangeSon = obj:FindLuaTableAttribute("SonRange")
  local override_height = obj:FindLuaTableAttribute("maxHeightRange") or 4
  if game.Boat.GetPlayerBoat() ~= nil then
    return false
  end
  if game.AIUtil.Distance(obj, player) > (override_range or MIN_PLAYER_DISTANCE) then
    return false
  end
  if game.AIUtil.Distance(obj:GetWorldPosition(), son:GetWorldPosition()) > (override_rangeSon or MIN_SON_DISTANCE) then
    return false
  end
  if override_height <= math.abs(obj:GetWorldPosition().y - son:GetWorldPosition().y) then
    return false
  end
  return true
end
local GetCameraPercent = function(obj)
  local scale = obj:FindLuaTableAttribute("CameraViewScalePercent") or 0
  return scale * 0.01 + 1
end
function UpdateInteraction(global, constants)
  local bestpen = MIN_CAMERA_PERCENT
  local foundOne
  if son_interact_state == INIT_STATE then
    Init()
    son_interact_state = CHECK_IN_VIEW_STATE
  elseif son_interact_state == CHECK_IN_VIEW_STATE then
    if global.potentialinteractWithThisPOI ~= nil and son.OwnedPOI == global.potentialinteractWithThisPOI then
      son_interact_state = SON_USE_POI_STATE
      return
    end
    global.potentialinteractWithThisPOI = nil
    if poilib.IsPOISearch() or poilib.IsPOIActive() then
      interactivePOIs = game.POI.FindAdvertising(player:GetWorldPosition(), 35, {
        "SON",
        "SONINTERACTABLE",
        MatchAll = true
      })
      for _, poi in ipairs(interactivePOIs) do
        if not CheckInteractRange(poi) then
          local hack = false
        else
          local checkPos = GetCheckPosition(poi)
          local penAmount = game.Camera.GetViewPenetration(checkPos, 0, 0) * GetCameraPercent(poi)
          if bestpen < penAmount then
            bestpen = penAmount
            foundOne = poi
          end
        end
      end
    end
    if foundOne then
      global.potentialinteractWithThisPOI = foundOne
      son_bb:Set("InteractObject", foundOne)
    else
      son_bb:Erase("InteractObject")
    end
  elseif son_interact_state == SON_USE_POI_STATE and son.OwnedPOI == nil then
    son_interact_state = CHECK_IN_VIEW_STATE
    return
  end
end
return {
  UpdateInteraction = UpdateInteraction
}
