local ML = require("design.MayaLuaTablesLibrary")
local callbacks_Enter, callbacks_Exit, ignore_navmesh, thisObj, sonPuppeteer
local inCubbyHole = false
local son
function OnScriptLoaded(level, obj)
  thisObj = obj
  son = game.AI.FindSon()
  local callbacks = obj:GetLuaTableAttribute("callbacksEnterHole")
  if callbacks then
    callbacks_Enter = ML.ExtractCallbacksForEvent(level, obj, callbacks)
  end
  callbacks = obj:GetLuaTableAttribute("callbacksExitHole")
  if callbacks then
    callbacks_Exit = ML.ExtractCallbacksForEvent(level, obj, callbacks)
  end
  ignore_navmesh = obj:GetLuaTableAttribute("IgnoreNavmesh")
  game.SubObject.Sleep(obj)
  game.SubObject.SetForgetOnCheckpoint(obj)
  obj:SetInhibitSave()
end
function Enable()
  CreatePuppeteer()
end
function Disable()
  ExitCubbyHole()
end
function Interrupt()
  Disable()
end
function CreatePuppeteer()
  if sonPuppeteer ~= nil then
    sonPuppeteer:Clear()
    sonPuppeteer = nil
  end
  sonPuppeteer = game.Puppeteer.New(thisObj, "CubbyHole", game.AI.FindSon())
  sonPuppeteer:SetStageName("CreatePuppeteer")
  if sonPuppeteer ~= nil then
    if son.OwnedPOI then
      if son.OwnedPOI.Type == "ContextAction" and son.OwnedPOI.LuaObjectScript and son.OwnedPOI.LuaObjectScript.Interrupt then
        son.OwnedPOI.LuaObjectScript.Interrupt()
      elseif son.OwnedPOI.Type == "CubbyHole" and son.OwnedPOI ~= thisObj and son.OwnedPOI.LuaObjectScript and son.OwnedPOI.LuaObjectScript.ClearPuppeteerAndAvailability then
        son:AbortInteract()
        son.OwnedPOI.LuaObjectScript.ClearPuppeteerAndAvailability()
      end
    end
    sonPuppeteer:SetType("CubbyHole")
    sonPuppeteer:Advertise("SON:AUTO")
    sonPuppeteer:OnEngaged(SonEngaged)
  end
end
function SonEngaged()
  son:SetNewAvailabilityRequest("ContextAction", {
    AvailableForSync = false,
    AvailableForCombat = false,
    Unoccupied = false
  })
  local sonDistanceToSync = (son:GetWorldPosition() - thisObj:GetWorldJointPosition(thisObj:GetJointIndex("approachJoint"))):Length()
  local approachSpeed = 6
  if sonDistanceToSync < 5 then
    approachSpeed = 2.2
  elseif sonDistanceToSync < 10 then
    approachSpeed = 4
  end
  local approachParams = {
    speed = approachSpeed,
    branch_name = "BRA_CA_Crawl_Enter",
    joint_name = "approachJoint",
    stop = false,
    stop_distance = 0.8,
    close_range_distance = 0.8,
    focus_end_direction = true,
    complete_radius = 0.8,
    ignore_navmesh = ignore_navmesh
  }
  if sonPuppeteer ~= nil then
    sonPuppeteer:Approach(approachParams)
    sonPuppeteer:SetStageName("Approach")
    sonPuppeteer:OnEvent(EnterCubbyHole, "ContextActionEarlyStopExit")
    sonPuppeteer:OnEvent(ClearPuppeteerAndAvailability, "BreakOut")
    sonPuppeteer:OnComplete(EnterCubbyHole)
  end
end
function EnterCubbyHole()
  print("Enter Cubby Hole")
  if sonPuppeteer ~= nil then
    sonPuppeteer:Clear()
    sonPuppeteer:Sync("BRA_CA_Crawl_Enter", true, {}, "approachJoint")
    sonPuppeteer:SetStageName("EnterCubbyHole")
    sonPuppeteer:OnEvent(ClearPuppeteerAndAvailability, "BreakOut")
    inCubbyHole = true
  end
end
function ExitCubbyHole()
  if sonPuppeteer ~= nil then
    if inCubbyHole and son.OwnedPOI and son.OwnedPOI == thisObj then
      inCubbyHole = false
      sonPuppeteer:StartBranch("BRA_CA_Crawl_Exit")
      sonPuppeteer:SetStageName("ExitCubbyHole")
      sonPuppeteer:OnComplete(ClearPuppeteerAndAvailability)
      sonPuppeteer:OnEvent(ClearPuppeteerAndAvailability, "BreakOut")
    else
      ClearPuppeteerAndAvailability()
    end
  end
end
function ClearPuppeteerAndAvailability()
  son:RemoveAvailabilityRequest("ContextAction")
  if sonPuppeteer ~= nil then
    if son.OwnedPOI and son.OwnedPOI == thisObj then
      sonPuppeteer:Clear()
    end
    sonPuppeteer:SetStageName("")
    sonPuppeteer:DetachPuppet()
    sonPuppeteer = nil
  end
end
function FireEnterCallbacks()
  if callbacks_Enter then
    for _, func in ipairs(callbacks_Enter) do
      func()
    end
  end
end
function FireExitCallbacks()
  if callbacks_Exit then
    for _, func in ipairs(callbacks_Exit) do
      func()
    end
  end
end
