local profile = require("core.profile")
local lazy_loaded_libraries = {
  ["design.PuppeteerLibrary"] = {
    SyncAndPlayBranch = true,
    Advertise_SyncAndPlayBranch = true,
    GoToLocation = true,
    Advertise_GoToLocation = true,
    MoveAndAlignToLocationSyncAndPlayBranch = true,
    GoToLocationSyncAndPlayBranch = true,
    Advertise_GoToLocationSyncAndPlayBranch = true,
    GoToLocationAlignAndWait = true,
    Advertise_GoToLocationAlignAndWait = true,
    PlayGroupSync = true,
    PlayApproach_GroupSync = true,
    GetGlobalApproachData = true,
    PlaySingleSynchMove_KratosObject = true,
    PlaySingleSynchMove_KratosSonObject = true
  },
  ["design.MayaLuaTablesLibrary"] = {
    ExtractAndExecuteCallbacksForEvent = true,
    ExtractCallbacksForEvent = true,
    ExecuteCallbacksForEvent = true,
    ConvertStringListToTable = true,
    ConvertTableToStringList = true,
    GetAnimFrameOrPercentInfoFromLuaTableAttr = true,
    FindAnimFrameOrPercentInfoFromLuaTableAttr = true,
    ExecuteSingleCallbackAndReturn = true,
    PostProcessAttributeCallbacks = true
  },
  ["design.NarrativeDesignLibrary"] = {
    FindFreya = true,
    SetFreyaSpawnGlobals = true,
    GetFreyaSpawnGlobals = true,
    CatchFreyaReference = true,
    TriggerFreyaSpawn = true,
    TriggerFreyaDelete = true,
    SpawnFreyaAtVector = true,
    MasterToLocationAndGroupSync = true,
    GroupToLocationsAndSyncBranch = true,
    MultiZoneGroupToLocationAndSync = true,
    GroupToLocationSyncAndIdle = true,
    SpawnAIAtJoint = true,
    CreateCineSequence = true
  },
  ["design.PrototypeLibrary"] = {
    PlayMove = true,
    Advertise_PlayMove = true,
    AlignAndPlayMove = true,
    Advertise_AlignAndPlayMove = true,
    GoToLocationAndPlayMove = true,
    Advertise_GoToLocationAndPlayMove = true,
    GoToLocationAlignAndPlayMove = true,
    Advertise_GoToLocationAlignAndPlayMove = true,
    SetAnimatedMaterialAttributes = true,
    AddAxeTarget = true,
    RemoveAxeTarget = true,
    ObjectIsInLight = true,
    ObjectHitByBifrost = true,
    ObjectIsInAlfLight = true
  },
  ["design.DebuggingLibrary"] = {
    GetParentTrace = true,
    DisplayAnimDebug = true,
    PrintToScreen = true
  },
  ["design.QuestLibrary"] = {
    ActivateQuest = true,
    CompleteQuest = true,
    ActivateAndIncrementQuest = true
  },
  ["design.SystemsDesignLibrary"] = {
    SetRegionDiscovered = true,
    RegionInfo_GetName = true,
    SetAllFTMarkersToDiscovered = true,
    UpdateJournal = true,
    UpdateMap = true,
    UnlockBestiaryEntry = true,
    UnlockBestiaryEntry_EndOfEncounter = true,
    CheckMapDiscoveryState = true,
    SetRealmDiscovered = true,
    SetMarkerState = true,
    SetFastTravelMarkerDiscovered = true,
    CheckFastTravelState = true,
    AddRecipe_Safe = true,
    SyncResurrectionStones = true,
    RollContainerConditionLoot = true,
    ConsumeNiflheimCurrency = true
  },
  ["design.MathLibrary"] = {
    GetAngleBetweenVector = true,
    GetPointAlongLine = true,
    GetPositionBetweenTwoPoints = true,
    GetXZDistanceBetweenTwoPoints = true
  },
  ["design.AudioLibrary"] = {
    PlayLoopingSoundToAnimFrame = true,
    PlaySoundAfterDelay = true,
    StopSoundAfterDelay = true,
    PlaySoundOnFrame = true,
    StopSoundOnFrame = true,
    PlaySound = true,
    PlaySoundRingOut = true,
    ReplaySound = true,
    PlayRestartableSoundLoop = true,
    StopSound = true,
    StopRestartableSoundLoop = true,
    TrackEmitterOnLine = true,
    SoundDebug = true,
    IsLoopingSound = true,
    StartCombatMusic = true,
    StopCombatMusic = true,
    EnableCombatBanter = true,
    DisableCombatBanter = true
  },
  ["design.SaveLibrary"] = {StoreCheckpointOverride = true},
  ["design.BoatBanterLibrary"] = {
    EnableBoatLore = true,
    EnableBoatLoreWithoutStoryTime = true,
    DisableBoatLore = true,
    DisableBoatLoreWithoutStoryTime = true,
    ResetSelectedLore = true,
    SetRecentlyActivatedQuest = true,
    UnlockGoodFellowsBoatLore = true,
    UnlockHrimthursRevengeBoatLore = true,
    UnlockMagniModiBoatLore = true,
    UnlockMimirBoatLore = true,
    UnlockTyrOdinBoatLore = true,
    UnlockPreMimirBoatLore = true,
    UnlockWrapOnMimirBoatLore = true,
    PlayEnterBoatBanter = true
  },
  ["design.CalderaLibrary"] = {
    GetRealmInfo = true,
    GetRealmFrame = true,
    Trigger_WaterDrop01 = true,
    Trigger_WaterDrop02 = true,
    Trigger_DragonArrival = true,
    GetCurrentWaterLevel = true,
    GetRealmFromValue = true,
    GetValueFromRealm = true,
    GetSelectedRealm = true,
    SetSelectedRealm = true,
    GetCurrentRealm = true,
    SetCurrentRealm = true,
    GetBridgePosition = true,
    SetBridgePosition = true,
    GetBridgeAnimationFrame = true,
    GetBridgeAnimationRate = true,
    GetCorrectedBridgeAnimRate = true,
    DisplayEntityDebug = true
  },
  ["design.EntityVariableMessagingLibrary"] = {RegisterForCineUpdate = true, RegisterForVariableUpdate = true},
  ["design.BanterLibrary"] = {EnableContextBehaviorBanter = true, DisableContextBehaviorBanter = true},
  ["design.ArrowLibrary"] = {
    GiveLightArrow = true,
    RemoveLightArrow = true,
    GiveShockArrow = true,
    RemoveShockArrow = true
  },
  ["design.AxeLibrary"] = {
    ForceAxeUnembed = true,
    PlayerSheathAxe = true,
    PlayerUnsheathAxe = true
  },
  ["design.BreakableLibrary"] = {BreakObject = true, RemoveBreakable = true},
  ["design.DelayLibrary"] = {PlayAnimToEndAfterDelay = true, CallFunctionAfterDelay = true},
  ["design.DeprecatedLibrary"] = {GetEntityVariable = true, SetEntityVariable = true},
  ["design.FXHelperLibrary"] = {
    ShowFX = true,
    HideFX = true,
    AddScreenShake = true,
    AddControllerRumble = true
  },
  ["design.InteractZone_CarryableLibrary"] = {CreateInteractZone_Carryable_360 = true},
  ["design.InteractZone_ConsumableStompLibrary"] = {CreateInteractZone_ConsumableStomp_360 = true},
  ["design.InteractZone_LootPickupLibrary"] = {CreateInteractZone_LootPickup_360 = true},
  ["design.InteractZone_StandardLibrary"] = {
    CreateInteractZone_Standard_90 = true,
    CreateInteractZone_Standard_180 = true,
    CreateInteractZone_Standard_360 = true
  },
  ["design.InteractZone_ThrowableLibrary"] = {CreateInteractZone_Throwable_360 = true},
  ["design.InteractZoneOverridesLibrary"] = {
    EnableInteractZoneGlint = true,
    OverrideInteractZone = true,
    OverrideInteractZoneTags = true
  },
  ["design.MarkerLibrary"] = {
    FindSingleAIByMarker = true,
    GetSingleAIByMarker = true,
    FindAllAIByMarker = true,
    MarkerIDsMatch = true
  },
  ["design.SonInteractZoneLibrary"] = {CreateSonInteractZone = true, CreateSonInteractZone_Dispell_180 = true},
  ["design.Unlock_BifrostLibrary"] = {GiveBifrost = true, GiveAllBifrost = true},
  ["design.Unlock_FastTravelLibrary"] = {
    GiveFastTravelStageOne = true,
    GiveFastTravelStageTwo = true,
    GiveFastTravelStageThree = true
  },
  ["design.UnlockLibrary"] = {
    GiveChisel = true,
    GiveDragonTooth = true,
    GiveTyrUnlock = true
  },
  ["design.UtilityLibrary"] = {
    ForwardUserFunctionToObject = true,
    Map = true,
    IMap = true,
    KeyMap = true
  },
  ["design.PositionalLibrary"] = {
    GetWorldJointPosition = true,
    GetWorldJointForward = true,
    SetFacingTowardObject = true,
    SetJointFacingTowardObject = true,
    GetPosInLocalSpaceOfObject = true,
    ProjectPositionOntoObject = true,
    GetDistanceBetweenTwoObjects = true,
    GetPositionBetweenTwoObjects = true,
    IsPositionInFrontOfObject = true,
    SnapObjectToFloor = true
  }
}
local mt_index_lazy_require = function(t, k)
  for libraryName, libraryFunctions in pairs(lazy_loaded_libraries) do
    if libraryFunctions[k] then
      local library = require(libraryName)
      local requestedFunction
      for functionName in pairs(libraryFunctions) do
        local fn = library[k]
        if functionName == k then
          requestedFunction = fn
        end
        t[k] = fn
      end
      if requestedFunction then
        return requestedFunction
      end
      return error("Loaded '", libraryName, "' to call function '", k, "', but that function doesn't exist.")
    end
  end
  return error("Could not find function \"", k, "\" in LevelDesignLibrary")
end
local make_leveldesignlibrary_package = function(t)
  profile.WrapLibrary(t)
  setmetatable(t, {__index = mt_index_lazy_require})
  return t
end
_G.GameObjects = {}
_G.GameObjectsMeta = {}
_G.GameObjectsMeta.cache = {}
function _G.GameObjectsMeta.__index(table, key)
  local entry = _G.GameObjectsMeta.cache[key]
  if entry == nil then
    entry = ActiveLevel:FindSingleGameObject(key)
    if entry == nil then
      error("In attempt to call GameObjects." .. tostring(key) .. " - Can't find game object '" .. tostring(key) .. "' in level '" .. ActiveLevel.Name .. "'")
    end
    _G.GameObjectsMeta.cache[key] = entry
  end
  return entry
end
setmetatable(_G.GameObjects, _G.GameObjectsMeta)
_G.GameObjectJoints = {}
_G.GameObjectJointsMeta = {}
_G.GameObjectJointsMeta.cache = {}
function _G.GameObjectJointsMeta.__index(table, key)
  local entry = _G.GameObjectJointsMeta.cache[key]
  if entry == nil then
    local obj = ActiveLevel:FindSingleGameObject(key)
    if obj == nil then
      error("In attempt to call GameObjectJoints." .. tostring(key) .. " - Can't find game object '" .. tostring(key) .. "' in level '" .. ActiveLevel.Name .. "'")
    end
    entry = {
      _GameObject = obj,
      _JointCache = {}
    }
    setmetatable(entry, _G.GameObjectJointsMeta2)
  end
  return entry
end
setmetatable(_G.GameObjectJoints, _G.GameObjectJointsMeta)
_G.GameObjectJointsMeta2 = {}
function _G.GameObjectJointsMeta2.__index(table, key)
  local entry = table._JointCache[key]
  if entry == nil then
    entry = table._GameObject:FindJointIndex(key)
    if entry == nil then
      local DebugLib = require("design.DebuggingLibrary")
      local parentTrace = DebugLib.GetParentTrace(table._GameObject)
      error("In attempt to call GameObjectJoints." .. table._GameObject:GetName() .. "." .. tostring(key) .. " - Can't find joint '" .. tostring(key) .. "' on game object '" .. table._GameObject:GetName() .. "' in level '" .. ActiveLevel.Name .. "'\n" .. parentTrace)
    end
    table._JointCache[key] = entry
  end
  return entry
end
_G.ExecuteLuaCallbacksFn = nil
function _G.ExecuteLuaCallbacks(level, go, callbacks)
  if not _G.ExecuteLuaCallbacksFn then
    local libraryName = "design.MayaLuaTablesLibrary"
    local functionName = "ExtractAndExecuteCallbacksForEvent"
    local library = require(libraryName)
    local fn = library[functionName]
    if not fn then
      return error("Loaded '", libraryName, "' to call function '", functionName, "', but that function doesn't exist.")
    end
    _G.ExecuteLuaCallbacksFn = fn
  end
  _G.ExecuteLuaCallbacksFn(level, go, callbacks)
end
return make_leveldesignlibrary_package({
  GameObjects = _G.GameObjects,
  GameObjectJoints = _G.GameObjectJoints
})
