local LD = require("design.LevelDesignLibrary")
local solved = false
local thisObj, doorRef, interactRef, drainR, drainL, drainC, interactScript, gear
local gearPinned = false
local gearAnimRate = 2
local gearChevronState = 0
local gearIceChevron
function OnScriptLoaded(level, obj)
  thisObj = obj
  doorRef = obj.Parent
  interactRef = doorRef.LuaObjectScript
  drainR = doorRef:FindSingleGOByName("BifrostDrain_R")
  drainL = doorRef:FindSingleGOByName("BifrostDrain_L")
  drainC = doorRef:FindSingleGOByName("BifrostDrain_C")
  if drainR ~= nil then
    drainR.LuaObjectScript.OnFullyLit(ActivateR_Door)
    drainR.LuaObjectScript.OnFullyUnlit(DeactivateR_Door)
  end
  if drainL ~= nil then
    drainL.LuaObjectScript.OnFullyLit(ActivateL_Door)
    drainL.LuaObjectScript.OnFullyUnlit(DeactivateL_Door)
  end
  if drainC ~= nil then
    drainC.LuaObjectScript.OnFullyLit(ActivateBothDoors)
    drainC.LuaObjectScript.OnFullyUnlit(DeactivateBothDoors)
  end
  interactScript = obj.Parent.LuaObjectScript
  interactScript.RegisterOnInteractStartCallback(SetDoorSolved)
  gear = obj.Parent:FindSingleGOByName("WallGear_Single_Hel")
  if gear ~= nil then
    gearIceChevron = obj.Parent:FindSingleGOByName("DrainDoorLock_L_Frozen")
    gear.LuaObjectScript.RegisterEmbedCallback(Lock)
    gear.LuaObjectScript.RegisterUnembedCallback(Unlock)
  end
  game.SubObject.Sleep(obj)
  SoundInit()
end
function OnFirstStart(level, obj)
  if drainR ~= nil and not drainR.LuaObjectScript.GetActive() then
    DeactivateR_Door()
  end
  if drainL ~= nil and not drainL.LuaObjectScript.GetActive() then
    DeactivateL_Door()
  end
  if drainC ~= nil and not drainC.LuaObjectScript.GetActive() then
    DeactivateBothDoors()
  end
end
function OnStart(level, obj)
  if solved then
    interactRef.Disable()
  else
    interactRef.OverrideInteractZone({hintXZRange = 12})
  end
end
function SetDoorSolved()
  if drainC == nil then
    solved = true
  end
end
function AnimateGear(rate)
  if gear ~= nil then
    gear.Child:PlayAnimCycle(rate)
    doorRef:OnAnimDone(thisObj, "StopGearAnim")
  end
end
function StopGearAnim()
  if gear ~= nil then
    gear.Child:PauseAnim()
    doorRef:ClearAllAnimCallbacks()
  end
end
function Lock()
  gearPinned = true
  gearIceChevron:PlayAnimToEnd(3)
  if drainL ~= nil then
    if drainL.LuaObjectScript.GetActive() then
      gearChevronState = 1
    else
      gearChevronState = 0
    end
  end
end
function Unlock()
  gearPinned = false
  gearIceChevron:PlayAnimToFrame(0, -6)
  if drainL ~= nil then
    if drainL.LuaObjectScript.GetActive() then
      if gearChevronState == 0 then
        gearChevronState = 1
        ActivateL_Door()
      end
    elseif gearChevronState == 1 then
      gearChevronState = 0
      DeactivateL_Door()
    end
  end
end
function ActivateL_Door()
  if not solved and not gearPinned then
    CheckDoors()
    if gear ~= nil then
      gearChevronState = 1
    end
    if drainR.LuaObjectScript.GetActive() then
      doorRef:StartAnim("leftLockOpen02")
    else
      doorRef:StartAnim("leftLockOpen")
    end
    AnimateGear(gearAnimRate)
  elseif solved and not gearPinned then
    if drainR.LuaObjectScript.GetActive() then
      doorRef:StartAnim("doorOpened_leftLockClose02")
    else
      doorRef:StartAnim("doorOpened_leftLockClose")
    end
    doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
    doorRef:PlayAnimToEnd(-1)
  end
  PlayLeftLockOpenSound()
end
function DeactivateL_Door()
  if not solved and not gearPinned then
    CheckDoors()
    if gear ~= nil then
      gearChevronState = 0
    end
    if drainR.LuaObjectScript.GetActive() then
      doorRef:StartAnim("leftLockOpen02")
      doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
      doorRef:PlayAnimToEnd(-1)
    else
      doorRef:StartAnim("leftLockOpen")
      doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
      doorRef:PlayAnimToEnd(-1)
    end
    AnimateGear(-gearAnimRate)
  elseif solved and not gearPinned then
    if drainR.LuaObjectScript.GetActive() then
      doorRef:StartAnim("doorOpened_leftLockClose02")
    else
      doorRef:StartAnim("doorOpened_leftLockClose")
    end
  end
  PlayLeftLockCloseSound()
end
function ActivateR_Door()
  if not solved then
    CheckDoors()
    if drainL.LuaObjectScript.GetActive() or gearChevronState == 1 then
      doorRef:StartAnim("rightLockOpen02")
    else
      doorRef:StartAnim("rightLockOpen")
    end
  elseif solved then
    if drainL.LuaObjectScript.GetActive() or gearChevronState == 1 then
      doorRef:StartAnim("doorOpened_rightLockClose02")
    else
      doorRef:StartAnim("doorOpened_rightLockClose")
    end
    doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
    doorRef:PlayAnimToEnd(-1)
  end
  PlayRightLockOpenSound()
end
function DeactivateR_Door()
  if not solved then
    CheckDoors()
    if drainL.LuaObjectScript.GetActive() or gearChevronState == 1 then
      doorRef:StartAnim("rightLockOpen02")
      doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
      doorRef:PlayAnimToEnd(-1)
    else
      doorRef:StartAnim("rightLockOpen")
      doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
      doorRef:PlayAnimToEnd(-1)
    end
  elseif solved then
    if drainL.LuaObjectScript.GetActive() or gearChevronState == 1 then
      doorRef:StartAnim("doorOpened_rightLockClose02")
    else
      doorRef:StartAnim("doorOpened_rightLockClose")
    end
  end
  PlayRightLockCloseSound()
end
function ActivateBothDoors()
  if not solved then
    doorRef:StartAnim("leftRightLockOpen")
    PlayLeftLockOpenSound()
    PlayRightLockOpenSound()
    interactRef.Unlock()
  end
end
function DeactivateBothDoors()
  if not solved then
    doorRef:StartAnim("leftRightLockOpen")
    doorRef:JumpAnimToFrame(doorRef.AnimLengthFrames)
    doorRef:PlayAnimToEnd(-1)
    PlayLeftLockCloseSound()
    PlayRightLockCloseSound()
    interactRef.Lock()
  end
end
function CheckDoors()
  if drainL.LuaObjectScript.GetActive() and drainR.LuaObjectScript.GetActive() or drainR.LuaObjectScript.GetActive() and gearChevronState == 1 then
    if interactRef ~= nil and not solved then
      interactRef.Unlock()
    end
  elseif interactRef ~= nil and not solved then
    interactRef.Lock()
  end
end
function OnSaveCheckpoint(level, obj)
  return {solved = solved}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  solved = savedInfo.solved
end
local soundEmitterLockLeft, soundEmitterLockRight
local soundEvents = {
  soundEmitterLockLeft = "SNDLockLeft",
  soundEmitterLockRight = "SNDLockRight",
  LockLeftOpen = "SND_DOOR_Hel_Exit_Latch_01",
  LockLeftClose = "SND_DOOR_Hel_Exit_Latch_01",
  LockRightOpen = "SND_DOOR_Hel_Exit_Latch_02",
  LockRightClose = "SND_DOOR_Hel_Exit_Latch_02"
}
function SoundInit()
  soundEmitterLockLeft = thisObj.Parent:FindSingleSoundEmitterByName(soundEvents.soundEmitterLockLeft)
  soundEmitterLockRight = thisObj.Parent:FindSingleSoundEmitterByName(soundEvents.soundEmitterLockRight)
  LD.SoundDebug(tostring(soundEmitterLockLeft) .. ": " .. tostring(soundEmitterLockRight) .. " | " .. tostring(soundEvents.soundEmitterLockLeft) .. ": " .. tostring(soundEvents.soundEmitterLockRight))
end
function SoundSetup(sounds)
  if sounds ~= nil then
    for k in pairs(soundEvents) do
      for newKey, newValue in pairs(sounds) do
        if newKey == k and newValue ~= nil and newValue ~= "" then
          soundEvents[k] = newValue
          LD.SoundDebug(tostring(k) .. ": " .. tostring(soundEvents[k]) .. " | " .. tostring(newKey) .. ": " .. tostring(newValue))
        end
      end
    end
    SoundInit()
  end
end
function PlayLeftLockOpenSound()
  LD.PlaySound(soundEmitterLockLeft, soundEvents.LockLeftOpen)
end
function PlayLeftLockCloseSound()
  LD.PlaySound(soundEmitterLockLeft, soundEvents.LockLeftClose)
end
function PlayRightLockOpenSound()
  LD.PlaySound(soundEmitterLockRight, soundEvents.LockRightOpen)
end
function PlayRightLockCloseSound()
  LD.PlaySound(soundEmitterLockRight, soundEvents.LockRightClose)
end
function GetSoundEmitter(emitterName)
  if emitterName ~= nil then
    return thisObj.Parent:FindSingleSoundEmitterByName(emitterName)
  else
    return nil
  end
end
