local LD = require("design.LevelDesignLibrary")
local son, thisLevel, thisObj
local enabled = false
local myPath, myPath_PlayerInteract, myLink, exitTopCallbacks, exitBottomCallbacks, ropeHeight, startEnabled, releaseRopeInteract, fiveMeterDropDisallowed, playerInteract, startPlayerInteractEnabled, axeOnBackTop, axeOnBackBottom
local startTraversalPathEnabled = true
local soundChainBottomEmitter
function OnScriptLoaded(level, obj)
  thisLevel = level
  thisObj = obj
  ropeHeight = obj:GetLuaTableAttribute("RopeHeight")
  startEnabled = obj:GetLuaTableAttribute("StartEnabled")
  fiveMeterDropDisallowed = obj:GetLuaTableAttribute("noDropDownAt5Meters")
  exitTopCallbacks = LD.ExtractCallbacksForEvent(level, obj, obj:GetLuaTableAttribute("ExitTopCallbacks"))
  exitBottomCallbacks = LD.ExtractCallbacksForEvent(level, obj, obj:GetLuaTableAttribute("ExitBottomCallbacks"))
  playerInteract = obj:GetLuaTableAttribute("PlayerInteract")
  startPlayerInteractEnabled = obj:GetLuaTableAttribute("StartPlayerInteractEnabled")
  axeOnBackTop = obj:GetLuaTableAttribute("AxeOnBackTop")
  axeOnBackBottom = obj:GetLuaTableAttribute("AxeOnBackBottom")
  startTraversalPathEnabled = obj:GetLuaTableAttribute("StartTraversalPathEnabled")
  myLink = obj:FindSingleGOByName("TraverseLink_" .. tostring(ropeHeight) .. "m")
  if ropeHeight == 5 and fiveMeterDropDisallowed then
    myPath = obj:FindSingleGOByName("TraversePath_5m_NoDropDown")
  else
    myPath = obj:FindSingleGOByName("TraversePath_" .. tostring(ropeHeight) .. "m")
  end
  myPath_PlayerInteract = obj:FindSingleGOByName("TraversePath_" .. tostring(ropeHeight) .. "m_PlayerInteract")
  releaseRopeInteract = obj:FindSingleGOByName("ReleaseRopeInteract")
  obj:RegisterAsChainedObject("attachJoint", ropeHeight, 75)
  soundChainBottomEmitter = thisObj:FindSingleSoundEmitterByName("SNDsoundChainBottom")
  game.SubObject.Sleep(obj)
end
function OnFirstPreStart(level, obj)
  HideTraversePaths()
  HideTraverseLinks()
  PlayLoop()
  if playerInteract then
    if startPlayerInteractEnabled then
      myPath_PlayerInteract:ShowTraversePath()
    else
      myPath_PlayerInteract:HideTraversePath()
    end
  end
  if startEnabled then
    Enable()
    DisableSonInteract()
  end
end
function SonReleaseRope()
  EnableSonInteract()
end
function EnableSonInteract()
  releaseRopeInteract.LuaObjectScript.Enable()
end
function DisableSonInteract()
  releaseRopeInteract.LuaObjectScript.DisableModule()
end
function EnablePlayerInteract()
  if not enabled then
    myPath_PlayerInteract:ShowTraversePath()
  end
end
function DisablePlayerInteract()
  myPath_PlayerInteract:HideTraversePath()
end
function ChainedObjectDrop()
  thisObj:ChainedObjectDrop()
  if soundChainBottomEmitter ~= nil then
    LD.PlaySound(soundChainBottomEmitter, "SND_MECH_Chain_Drop_Kick_Off_Ledge")
  end
end
function Enable()
  enabled = true
  local immediate = startEnabled ~= nil and startEnabled
  thisObj:ChainedObjectDrop(immediate)
  myPath_PlayerInteract:HideTraversePath()
  if startTraversalPathEnabled then
    if immediate == true then
      myPath:ShowTraversePath()
    else
      LD.CallFunctionAfterDelay(function()
        myPath:ShowTraversePath()
      end, GetDropTimeFromChainHeight())
    end
  end
  if not fiveMeterDropDisallowed then
    if myLink then
      if immediate == true then
        myLink:ShowTraverseLink()
      else
        LD.CallFunctionAfterDelay(function()
          myLink:ShowTraverseLink()
        end, GetDropTimeFromChainHeight())
      end
    end
    if ropeHeight <= 5 then
      local ledgeCollision = thisObj:FindSingleGOByName("LedgeCollision")
      if ledgeCollision then
        ledgeCollision:HideCollision()
      end
    end
  end
  if myPath.GetTraversePath then
    local flag = "Axe on Back"
    local traversePath = myPath:GetTraversePath()
    if traversePath and axeOnBackTop then
      traversePath:SetFlag("Top", flag)
    end
    if traversePath and axeOnBackBottom then
      traversePath:SetFlag("Bottom", flag)
    end
  end
end
function GetDropTimeFromChainHeight()
  return math.sqrt(2 * ropeHeight / 9.8)
end
function Disable()
  enabled = false
  myPath:HideTraversePath()
end
function DisableTraversePath()
  myPath:HideTraversePath()
  myPath_PlayerInteract:HideTraversePath()
end
function EnableTraversePath()
  if playerInteract and enabled == false then
    myPath_PlayerInteract:ShowTraversePath()
  else
    myPath:ShowTraversePath()
  end
end
function HideTraversePaths()
  thisObj:FindSingleGOByName("TraversePath_5m_NoDropDown"):HideTraversePath()
  for i = 2, 13 do
    thisObj:FindSingleGOByName("TraversePath_" .. i .. "m"):HideTraversePath()
    thisObj:FindSingleGOByName("TraversePath_" .. i .. "m_PlayerInteract"):HideTraversePath()
  end
end
function HideTraverseLinks()
  for i = 2, 13 do
    local go = thisObj:FindSingleGOByName("TraverseLink_" .. i .. "m")
    if go then
      go:HideTraverseLink()
    end
  end
end
function IsParent()
  return true
end
function OnSaveCheckpoint(level, go)
  return {enabled = enabled}
end
function OnRestoreCheckpoint(level, go, savedInfo)
  if savedInfo.enabled then
    startEnabled = true
    Enable()
  else
    Disable()
  end
  PlayLoop()
end
function ExecuteExitTopCallbacks()
  LD.ExecuteCallbacksForEvent(thisLevel, thisObj, exitTopCallbacks)
end
function ExecuteExitBottomCallbacks()
  LD.ExecuteCallbacksForEvent(thisLevel, thisObj, exitBottomCallbacks)
end
function PlayLoop()
  if soundChainBottomEmitter ~= nil then
    if not soundChainBottomEmitter:IsPlaying("SND_MECH_Chain_Drop_Movement_LP") then
      LD.CallFunctionAfterDelay(function()
        LD.PlayRestartableSoundLoop(soundChainBottomEmitter, "SND_MECH_Chain_Drop_Movement_LP")
      end, 0.02)
    end
  else
    soundChainBottomEmitter = thisObj:FindSingleSoundEmitterByName("SNDsoundChainBottom")
  end
end
function PlayDrop()
  LD.PlaySoundAfterDelay(soundChainBottomEmitter, "SND_MECH_Chain_Drop_Son_Toss", 3.7)
end
function PlaySoundOnObjectEmitter(snd)
  LD.PlaySound(soundChainBottomEmitter, snd)
end
