local monitors = require("level.MonitorLibrary")
local son, playerSide, sonSide, zoneForceCrawl
local sideA = {}
local sideB = {}
local gateObj
local frameThreshold = 0
local frameZeroDown = true
local FrameEvalFunc
function OnScriptLoaded(level, obj)
  son = game.AI.FindSon()
  sideA.Point = obj:FindSingleGOByName("Point_A").Child.LuaObjectScript
  sideB.Point = obj:FindSingleGOByName("Point_B").Child.LuaObjectScript
  sideA.Zone = obj:FindSingleGOByName("zoneA")
  game.SubObject.SetEntityZoneHandler(obj, sideA.Zone)
  sideB.Zone = obj:FindSingleGOByName("zoneB")
  game.SubObject.SetEntityZoneHandler(obj, sideB.Zone)
  local zoneName = obj:FindLuaTableAttribute("zoneSideA_Additional")
  if zoneName and zoneName ~= "" then
    sideA.AdditionalZone = GameObjects[zoneName]
    game.SubObject.SetEntityZoneHandler(obj, sideA.AdditionalZone)
  end
  zoneName = obj:FindLuaTableAttribute("zoneSideB_Additional")
  if zoneName and zoneName ~= "" then
    sideB.AdditionalZone = GameObjects[zoneName]
    game.SubObject.SetEntityZoneHandler(obj, sideB.AdditionalZone)
  end
  zoneForceCrawl = obj:FindLuaTableAttribute("zoneOptionalForceCrawl")
  if zoneForceCrawl and zoneForceCrawl ~= "" then
    zoneForceCrawl = GameObjects[zoneForceCrawl]
    game.SubObject.SetEntityZoneHandler(obj, zoneForceCrawl)
  end
  local gateName = obj:GetLuaTableAttribute("gateObj")
  if gateName and gateName ~= "" then
    gateObj = GameObjects[gateName]
    frameThreshold = obj:GetLuaTableAttribute("gateFrameThreshold")
  end
  sideA.Auto = obj:FindLuaTableAttribute("autoCrawl_AToB")
  sideB.Auto = obj:FindLuaTableAttribute("autoCrawl_BToA")
  frameZeroDown = obj:FindLuaTableAttribute("frameZeroIsDown")
  game.SubObject.Sleep(obj)
  game.SubObject.SetForgetOnCheckpoint(obj)
end
function OnStart(level, obj)
  if sideA.Auto or sideB.Auto then
    local gateMonitor = monitors.CreateAnimFrameMonitor(gateObj)
    if frameZeroDown then
      FrameEvalFunc = FrameEvalDown
      gateMonitor:OnFrameBackward(frameThreshold, AutoCrawl)
    else
      FrameEvalFunc = FrameEvalUp
      gateMonitor:OnFrameForward(frameThreshold, AutoCrawl)
    end
  end
end
function OnMarkerEnterZone(level, scriptObj, volumeGameObject, markerGameObject, markerId)
  if tostring(markerId) == tostring(3) then
    if zoneForceCrawl == volumeGameObject then
      TriggerCrawl()
    else
      local zoneSide = GetZoneSide(volumeGameObject)
      if playerSide ~= zoneSide then
        playerSide = zoneSide
        if sonSide == nil then
          sonSide = zoneSide
        else
          AutoCrawl()
        end
      end
    end
  elseif tostring(markerId) == tostring(5) and volumeGameObject ~= zoneForceCrawl then
    local zoneSide = GetZoneSide(volumeGameObject)
    if sonSide ~= zoneSide then
      sonSide = zoneSide
      if playerSide == nil then
        playerSide = zoneSide
      else
        AutoCrawl()
      end
    end
  end
end
function AutoCrawl()
  if sonSide and sonSide.Auto then
    TriggerCrawl()
  end
end
function TriggerCrawl()
  if sonSide ~= playerSide and son:IsAvailableInLevel() then
    if gateObj ~= nil and FrameEvalFunc() then
      sonSide.Point.Enable()
      playerSide.Point.Disable()
    end
  else
    sideA.Point.Disable()
    sideB.Point.Disable()
  end
end
function CralwStart()
  if sonSide == sideA then
    if son ~= nil and son:IsInsideEntityZone(sideB.Zone) then
      sonSide = sideB
    end
  elseif son ~= nil and son:IsInsideEntityZone(sideA.Zone) then
    sonSide = sideA
  end
end
function GetZoneSide(testZone)
  if testZone == sideA.Zone or testZone == sideA.AdditionalZone then
    return sideA
  else
    return sideB
  end
end
function FrameEvalDown()
  return gateObj.AnimFrame <= frameThreshold
end
function FrameEvalUp()
  return gateObj.AnimFrame >= frameThreshold
end
