local LD = require("design.LevelDesignLibrary")
local timers, thisObj, thisLevel, markers, entryCallbacks, exitCallbacks, entryForwardCallbacks, exitForwardCallbacks, entryBackwardCallbacks, exitBackwardCallbacks, usePlayer, useSon, callbackDelay, timeRemaining_Enter, callbackDelayTimer_Enter, timeRemaining_Exit, callbackDelayTimer_Exit
local enabled = true
local disableAfterUse
local triggerLimit = 0
local triggered = 0
local timers_LoadLibrary = function()
  if timers == nil then
    timers = require("level.timer")
  end
end
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  disableAfterUse = thisObj:GetLuaTableAttribute("disableAfterUse")
  usePlayer = thisObj:GetLuaTableAttribute("usePlayer")
  useSon = thisObj:GetLuaTableAttribute("useSon")
  markers = thisObj:GetLuaTableAttribute("markers")
  callbackDelay = thisObj:GetLuaTableAttribute("callbackDelay")
  markers = LD.ConvertStringListToTable(markers)
  if obj:FindLuaTableAttribute("zoneForwardEntryCallbacks") ~= nil and obj:FindLuaTableAttribute("zoneForwardEntryCallbacks") ~= "" then
    entryForwardCallbacks = LD.ExtractCallbacksForEvent(level, thisObj, obj:FindLuaTableAttribute("zoneForwardEntryCallbacks"))
    triggerLimit = triggerLimit + 1
  end
  if obj:FindLuaTableAttribute("zoneForwardExitCallbacks") ~= nil and obj:FindLuaTableAttribute("zoneForwardExitCallbacks") ~= "" then
    exitForwardCallbacks = LD.ExtractCallbacksForEvent(level, thisObj, obj:FindLuaTableAttribute("zoneForwardExitCallbacks"))
    triggerLimit = triggerLimit + 1
  end
  if obj:FindLuaTableAttribute("zoneBackwardEntryCallbacks") ~= nil and obj:FindLuaTableAttribute("zoneBackwardEntryCallbacks") ~= "" then
    entryBackwardCallbacks = LD.ExtractCallbacksForEvent(level, thisObj, obj:FindLuaTableAttribute("zoneBackwardEntryCallbacks"))
    triggerLimit = triggerLimit + 1
  end
  if obj:FindLuaTableAttribute("zoneBackwardExitCallbacks") ~= nil and obj:FindLuaTableAttribute("zoneBackwardExitCallbacks") ~= "" then
    exitBackwardCallbacks = LD.ExtractCallbacksForEvent(level, thisObj, obj:FindLuaTableAttribute("zoneBackwardExitCallbacks"))
    triggerLimit = triggerLimit + 1
  end
  if usePlayer then
    markers[#markers + 1] = 3
  end
  if useSon then
    markers[#markers + 1] = 5
  end
  local refnode = obj.Parent
  local zoneParent = refnode.Parent
  if game.SubObject.SetEntityZoneHandler then
    game.SubObject.SetEntityZoneHandler(obj, zoneParent)
  end
  game.SubObject.Sleep(obj)
end
function OnStart(level, obj)
  if timeRemaining_Enter ~= nil then
    timers_LoadLibrary()
    callbackDelayTimer_Enter = timers.StartLevelTimer(timeRemaining_Enter, FireEnterCallbacks)
  end
  if timeRemaining_Exit ~= nil then
    timers_LoadLibrary()
    callbackDelayTimer_Exit = timers.StartLevelTimer(timeRemaining_Exit, FireExitCallbacks)
  end
end
function Enable()
  enabled = true
end
function Disable()
  enabled = false
end
function OnMarkerEnterZone(level, scriptObj, volumeGameObject, markerGameObject, markerId)
  print(volumeGameObject)
  local forwardDistance = markerGameObject.WorldPosition:Distance(thisObj:GetWorldJointPosition(thisObj:GetJointIndex("forward")))
  local backwardDistance = markerGameObject.WorldPosition:Distance(thisObj:GetWorldJointPosition(thisObj:GetJointIndex("backward")))
  if forwardDistance > backwardDistance then
    entryCallbacks = entryForwardCallbacks
  elseif forwardDistance < backwardDistance then
    entryCallbacks = entryBackwardCallbacks
  else
    print("Please place directional entity near the center of the trigger volume; you have managed to enter at a point equidistant from the forward and behind points.  This should probably be a warning but I don't know how and can't be bothered.")
  end
  if entryCallbacks ~= nil and enabled then
    for _, marker in ipairs(markers) do
      if game.LargeInteger.HashString(marker) == markerId or game.LargeInteger.HashString(marker) == game.LargeInteger.HashString(tostring(markerId)) then
        if 0 < callbackDelay then
          timers_LoadLibrary()
          callbackDelayTimer_Enter = timers.StartLevelTimer(callbackDelay, FireEnterCallbacks)
        else
          FireEnterCallbacks()
        end
        if disableAfterUse then
          triggered = triggered + 1
          if triggered == triggerLimit then
            Disable()
          end
        end
        return
      end
    end
  end
end
function FireEnterCallbacks()
  if callbackDelayTimer_Enter ~= nil then
    callbackDelayTimer_Enter:Stop()
    callbackDelayTimer_Enter = nil
  end
  if entryCallbacks then
    LD.ExecuteCallbacksForEvent(thisLevel, thisObj, entryCallbacks, "Zone Entry Callback for object '" .. LD.GetParentTrace(thisObj) .. "'")
  end
end
function OnMarkerExitZone(level, scriptObj, volumeGameObject, markerGameObject, markerId)
  print(volumeGameObject)
  local forwardDistance = markerGameObject.WorldPosition:Distance(thisObj:GetWorldJointPosition(thisObj:GetJointIndex("forward")))
  local backwardDistance = markerGameObject.WorldPosition:Distance(thisObj:GetWorldJointPosition(thisObj:GetJointIndex("backward")))
  if forwardDistance < backwardDistance then
    exitCallbacks = exitForwardCallbacks
  elseif forwardDistance > backwardDistance then
    exitCallbacks = exitBackwardCallbacks
  else
    print("Please place directional entity near the center of the trigger volume; you have managed to enter at a point equidistant from the forward and behind points.  This should probably be a warning but I don't know how and can't be bothered.")
  end
  if exitCallbacks ~= nil and enabled then
    for _, marker in ipairs(markers) do
      if game.LargeInteger.HashString(marker) == markerId or game.LargeInteger.HashString(marker) == game.LargeInteger.HashString(tostring(markerId)) then
        if 0 < callbackDelay then
          timers_LoadLibrary()
          callbackDelayTimer_Exit = timers.StartLevelTimer(callbackDelay, FireExitCallbacks)
        else
          FireExitCallbacks()
        end
        if disableAfterUse then
          triggered = triggered + 1
          if triggered == triggerLimit then
            Disable()
          end
        end
        return
      end
    end
  end
end
function FireExitCallbacks()
  if callbackDelayTimer_Exit ~= nil then
    callbackDelayTimer_Exit:Stop()
    callbackDelayTimer_Exit = nil
  end
  LD.ExecuteCallbacksForEvent(thisLevel, thisObj, exitCallbacks, "Zone Exit Callback for object '" .. LD.GetParentTrace(thisObj) .. "'")
end
function OnSaveCheckpoint(level, obj)
  timeRemaining_Enter = nil
  timeRemaining_Exit = nil
  if callbackDelayTimer_Enter ~= nil and callbackDelayTimer_Enter.running then
    timeRemaining_Enter = callbackDelayTimer_Enter:GetRemainingTime()
  end
  if callbackDelayTimer_Exit ~= nil and callbackDelayTimer_Exit.running then
    timeRemaining_Exit = callbackDelayTimer_Exit:GetRemainingTime()
  end
  return {
    enabled = enabled,
    timeRemaining_Enter = timeRemaining_Enter,
    timeRemaining_Exit = timeRemaining_Exit
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  enabled = savedInfo.enabled
  timeRemaining_Enter = savedInfo.timeRemaining_Enter
  timeRemaining_Exit = savedInfo.timeRemaining_Exit
end
