local banterToTrigger
local timers = require("creature.timer")
local contextlist = {
  LeadTheWay = "LEAD_THE_WAY_BEHAVIOR_CONTEXT_CONFIG",
  WaitAndExplore = "WAIT_AND_EXPLORE_BEHAVIOR_CONTEXT_CONFIG",
  Sad = "SAD_BEHAVIOR_CONTEXT_CONFIG",
  Frustrated = "FRUSTRATED_BEHAVIOR_CONTEXT_CONFIG",
  Panic = "PANIC_BEHAVIOR_CONTEXT_CONFIG",
  LookAround = "NORMAL_LOOKAROUND_BEHAVIOR_CONTEXT_CONFIG",
  Cold = "COLD_BEHAVIOR_CONTEXT_CONFIG",
  NearPoison = "WAIT_AND_EXPLORE_BEHAVIOR_CONTEXT_CONFIG",
  Puzzled = "PUZZLED_BEHAVIOR_CONTEXT_CONFIG",
  Boat_Lookat = "BOAT_CONTEXT_CONFIG_LEFT",
  Boat_Sick = "BOAT_SICK_CONTEXT_CONFIG",
  Will_Not_Fight = "WILL_NOT_FIGHT_BEHAVIOR_CONTEXT_CONFIG",
  Sick = "SICK_BEHAVIOR_CONTEXT_CONFIG",
  Bored = "BORED_BEHAVIOR_CONTEXT_CONFIG",
  Normal = "NORMAL_BEHAVIOR_CONTEXT_CONFIG",
  Nervous = "NERVOUS_CONTEXT_CONFIG",
  Alert = "ALERT_BEHAVIOR_CONTEXT_CONFIG"
}
local HandleEnvironmentEvent = function(ai, event)
  _G._EnvironmentEventWarpTarget = event.SourcePosition
  _G._EnvironmentEventStage = event.ReactionStage
  local syncing = ai:IsSyncSlave() or ai:IsDoingSyncMove() and (not _G.global.POIInfo or not _G.global.POIInfo.POIType or _G.global.POIInfo.POIType ~= "ContextAction")
  if syncing then
    return
  end
  if event.LuaEvent then
    ai:TriggerMoveEvent(event.LuaEvent)
  end
  banterToTrigger = event.Banter
end
local GetOutcomeBranch = function(position, forward, branch, target, forwardAngleConstraint, backwardAngleConstraint)
  local to = target - position
  local angle = game.AIUtil.AngleBetweenXZ(forward, to)
  if angle >= -forwardAngleConstraint and forwardAngleConstraint >= angle then
    return branch:FindOutcomeBranchesEntry("Forward")
  elseif angle <= -forwardAngleConstraint and angle >= -(180 - backwardAngleConstraint) then
    return branch:FindOutcomeBranchesEntry("Left")
  elseif forwardAngleConstraint <= angle and angle <= 180 - backwardAngleConstraint then
    return branch:FindOutcomeBranchesEntry("Right")
  else
    return branch:FindOutcomeBranchesEntry("Behind")
  end
end
local LuaHook_ActivateAlertContextBehavior = function(ai, branch)
  ai:CallScript("EnterBehaviorContextAtIdle", "ALERT_BEHAVIOR_CONTEXT_CONFIG")
end
local LuaHook_GetEnvironmentEventBranch = function(ai, branch)
  local target = _G._EnvironmentEventWarpTarget
  if target == nil then
    return
  end
  local forward = ai:GetWorldForward()
  local position = ai:GetWorldPosition()
  return GetOutcomeBranch(position, forward, branch, target, 30, 30)
end
local LuaHook_GetEnvironmentEventBranchInBoat = function(ai, branch)
  local target = _G._EnvironmentEventWarpTarget
  if target == nil then
    return
  end
  local forward = -game.Player.FindPlayer():GetWorldForward()
  local position = ai:GetWorldPosition()
  return GetOutcomeBranch(position, forward, branch, target, 30, 15)
end
local LuaHook_GetEnvironmentEventStage = function(ai, branch)
  local stage = _G._EnvironmentEventStage
  if stage == 1 then
    return branch:FindOutcomeBranchesEntry("FirstReaction")
  elseif stage == 2 then
    return branch:FindOutcomeBranchesEntry("SecondReaction")
  elseif stage == 3 then
    return branch:FindOutcomeBranchesEntry("ThirdReaction")
  end
end
local LuaHook_GetEnvironmentLeftOrRightBranch = function(ai, branch)
  local target = _G._EnvironmentEventWarpTarget
  if target == nil then
    return
  end
  local forward = ai:GetWorldForward()
  local position = ai:GetWorldPosition()
  return GetOutcomeBranch(position, forward, branch, target, 0, 0)
end
local LuaHook_GetEnvironmentLeftOrRightBranchInBoat = function(ai, branch)
  local target = _G._EnvironmentEventWarpTarget
  if target == nil then
    return
  end
  local forward = -game.Player.FindPlayer():GetWorldForward()
  local position = ai:GetWorldPosition()
  return GetOutcomeBranch(position, forward, branch, target, 0, 0)
end
local LuaHook_GetEnvironmentEvent_DistanceBranch = function(ai, branch)
  local to = (game.Player.FindPlayer():GetWorldPosition() - ai:GetWorldPosition()):Length()
  if 15 <= to then
    return branch:FindOutcomeBranchesEntry("Exit")
  end
end
local LuaHook_PlayEnvEventBanter = function()
  print("Attempting to play EnvironmentEvent Banter: ", banterToTrigger)
  if banterToTrigger then
    game.Audio.PlayBanterNonCritical(banterToTrigger)
  end
end
local SetSourcePositionAndTriggerMove = function(ai, obj, stageNumber, attributes)
  _G._EnvironmentEventWarpTarget = obj:GetWorldPosition()
  local luaEvent
  if stageNumber == 1 then
    luaEvent = attributes.StageOneMove
  elseif stageNumber == 2 then
    luaEvent = attributes.StageTwoMove
  elseif stageNumber == 3 then
    luaEvent = attributes.StageThreeMove
  end
  if luaEvent and luaEvent ~= "" then
    ai:TriggerMoveEvent(luaEvent)
  end
end
local contextOnExit, contextOnExitDelay
local SetContext = function(ai, newContext)
  print("Setting Context to: ", contextOnExit, " after a delay of: ", contextOnExitDelay)
  if newContext == "ClearContext" then
    ai:CallScript("ClearBehaviorContext")
  else
    ai:CallScript("EnterBehaviorContext", contextlist[newContext])
  end
end
local SetContext_OnExit = function(ai, context, contextDelay)
  contextOnExit = context
  contextOnExitDelay = contextDelay
end
local LuaHook_SetContext_OnExit = function(ai)
  if contextOnExit and contextOnExit ~= "KeepCurrentContext" then
    if contextOnExitDelay <= 0 then
      SetContext(ai, contextOnExit)
    else
      timers.StartCreatureTimer(contextOnExitDelay, function()
        SetContext(ai, contextOnExit)
      end)
    end
  end
end
local InstallHooks = function()
  _G.OnEnvironmentEvent = HandleEnvironmentEvent
  _G.LuaHook_GetEnvironmentEventBranch = LuaHook_GetEnvironmentEventBranch
  _G.LuaHook_GetEnvironmentEventBranchInBoat = LuaHook_GetEnvironmentEventBranchInBoat
  _G.LuaHook_GetEnvironmentEventStage = LuaHook_GetEnvironmentEventStage
  _G.LuaHook_GetEnvironmentLeftOrRightBranch = LuaHook_GetEnvironmentLeftOrRightBranch
  _G.LuaHook_GetEnvironmentLeftOrRightBranchInBoat = LuaHook_GetEnvironmentLeftOrRightBranchInBoat
  _G.LuaHook_GetEnvironmentEvent_DistanceBranch = LuaHook_GetEnvironmentEvent_DistanceBranch
  _G.LuaHook_ActivateAlertContextBehavior = LuaHook_ActivateAlertContextBehavior
  _G.LuaHook_PlayEnvEventBanter = LuaHook_PlayEnvEventBanter
  _G.LuaHook_SetContext_OnExit = LuaHook_SetContext_OnExit
  _G.SetContext_OnExit = SetContext_OnExit
  _G.SetSourcePositionAndTriggerMove = SetSourcePositionAndTriggerMove
end
return {InstallHooks = InstallHooks, HandleEnvironmentEvent = HandleEnvironmentEvent}
