local LD = require("design.LevelDesignLibrary")
require("level.timer")
local thisObj, thisLevel, enabled, temporalObject, onCrystalFullyLitEvents, onCrystalFullyUnlitEvents, socketed, fullyLitCallbacks, fullyUnlitCallbacks, subFX, nestedFX, pulseFX, fullyLitMesh
local crystalActive = false
local isShadowCaster, shadowCastingLight, normalLight, defaultLight
findObjectTemporalOnly = nil
bridgeCount = 0
bridgesOff = 0
function OnScriptLoaded(level, obj)
  thisObj = obj
  thisLevel = level
  obj:AddMarker("SonTarget")
  local parentObj = obj.Parent
  findObjectTemporalOnly = obj:GetLuaTableAttribute("FindObjecTemporalOnly")
  if obj:FindLuaTableAttribute("CrystalFullyLit") ~= nil then
    onCrystalFullyLitEvents = LD.ExtractCallbacksForEvent(level, obj, obj:FindLuaTableAttribute("CrystalFullyLit"))
  end
  if obj:FindLuaTableAttribute("CrystalFullyUnlit") ~= nil then
    onCrystalFullyUnlitEvents = LD.ExtractCallbacksForEvent(level, obj, obj:FindLuaTableAttribute("CrystalFullyUnlit"))
  end
  if obj:FindLuaTableAttribute("TemporalObject") ~= nil and obj:FindLuaTableAttribute("TemporalObject") ~= "" then
    if findObjectTemporalOnly then
      temporalObject = obj:FindSingleGOByName("temporalBrazier")
    else
      temporalObject = level:GetGameObject(tostring(obj:FindLuaTableAttribute("TemporalObject")))
    end
  end
  enabled = obj:GetLuaTableAttribute("Enabled")
  crystalActive = obj:GetLuaTableAttribute("CrystalActive")
  isShadowCaster = obj:GetLuaTableAttribute("IsShadowCaster")
  print("IS SHADOW CASTER ....", isShadowCaster)
  fullyLitMesh = obj:FindSingleGOByName("FullyLitMesh")
  normalLight = obj:FindSingleGOByName("NormalLight")
  defaultLight = obj:FindSingleGOByName("DefaultLight_OffState")
  shadowCastingLight = obj:FindSingleGOByName("ShadowCasterLight")
  pulseFX = obj:FindSingleGOByName("bifrost_crystal_temporal_pulse")
  pulseFX:Hide()
  subFX = obj:FindSingleGOByName("bifrost_crystal_temporal_active")
  subFX:Hide()
  print("SUB FX IS.....", subFX)
  nestedFX = subFX:FindSingleGOByName("bifrost_temporal_active")
  SoundInit()
  print("Temporal Object is...", temporalObject)
  game.SubObject.Sleep(obj)
end
function OnFirstStart(level, obj)
  if crystalActive then
    SetCrystalObjectStates(2)
  elseif not crystalActive and socketed then
    SetCrystalObjectStates(1)
  else
    SetCrystalObjectStates(0)
  end
end
function OnHitByArrow(level, go, arrow_owner, arrow_go, arrow_tweak)
  if arrow_go:GetName() == "bifrost_projectile" and enabled then
    if not crystalActive then
      SetCrystalObjectStates(2)
      print("WAS PRISMATIC")
      if thisObj:GetLuaTableAttribute("OnCrystalLitFirstTime") ~= nil then
        LD.ExtractAndExecuteCallbacksForEvent(thisLevel, thisObj, thisObj:GetLuaTableAttribute("OnCrystalLitFirstTime"), "Crystal first light")
      end
      PlaySoundActivateCrystal()
    else
      SetCrystalObjectStates(3)
      ActivatePulse()
    end
  else
    print("Must be something else")
  end
end
function ActivatePulse()
  local objPos = thisObj:GetWorldPosition()
  local pulseFX = game.FX.Spawn("bifrost_crystal_temporal_pulse", thisLevel, {AutoDelete = true})
  pulseFX:SetWorldPosition(objPos)
  local concussionParams = {
    Tweak = "CNC_Light_Crystal_Pulse",
    WorldLocation = objPos,
    GameObject = thisObj,
    EnemyId = game.AI.FindSon():GetID()
  }
  game.Combat.PlayConcussion(concussionParams)
  PlayLightPulseSound()
end
function OnFullyLit(functionToCall)
  if fullyLitCallbacks == nil then
    fullyLitCallbacks = {}
  end
  table.insert(fullyLitCallbacks, functionToCall)
end
function FireFullyLitCallbacks()
  if fullyLitCallbacks ~= nil then
    for i = 1, #fullyLitCallbacks do
      fullyLitCallbacks[i]()
    end
  end
end
function OnFullyUnlit(functionToCall)
  if fullyUnlitCallbacks == nil then
    fullyUnlitCallbacks = {}
  end
  table.insert(fullyUnlitCallbacks, functionToCall)
end
function FireFullyUnlitCallbacks()
  if fullyUnlitCallbacks ~= nil then
    for i = 1, #fullyUnlitCallbacks do
      fullyUnlitCallbacks[i]()
    end
  end
end
function SetCrystalObjectStates(data)
  if data == 0 then
    print("Temporal Crystal State 0")
    DisableTemporalObject()
    fullyLitMesh:Hide()
    normalLight:PauseAnim()
    normalLight:Hide()
    defaultLight:Show()
    defaultLight:PlayAnimCycle()
    shadowCastingLight:PauseAnim()
    shadowCastingLight:Hide()
    fullyLitMesh:PauseAnim()
    crystalActive = false
    FireFullyUnlitCallbacks()
    LD.ExecuteCallbacksForEvent(thisLevel, thisObj, onCrystalFullyUnlitEvents, "CrystalFullyUnlitEvents")
    SetSoundBifrostInactive()
  elseif data == 1 then
    print("Temporal Crystal State 1")
    DisableTemporalObject()
    fullyLitMesh:Hide()
    normalLight:Hide()
    defaultLight:Show()
    defaultLight:PlayAnimCycle()
    shadowCastingLight:Hide()
    fullyLitMesh:PauseAnim()
    fullyLitMesh:PauseAnim()
    shadowCastingLight:PauseAnim()
    subFX:Hide()
    fullyLitMesh:PauseAnim()
    SetSoundBifrostInactive()
  elseif data == 2 then
    print("Temporal Crystal State 2")
    fullyLitMesh:Show()
    defaultLight:Hide()
    if isShadowCaster then
      print("showing shadow caster light")
      shadowCastingLight:Show()
      shadowCastingLight:PlayAnimCycle()
    else
      print("showing normal light")
      normalLight:Show()
      normalLight:PlayAnimCycle()
    end
    nestedFX:JumpAnimToFrame(0)
    nestedFX:PlayAnimToFrame(20)
    nestedFX:OnAnimationDone(thisObj, "CrystalFXPeaked", {Force = true})
    nestedFX:Show()
    crystalActive = true
    FireFullyLitCallbacks()
    LD.ExecuteCallbacksForEvent(thisLevel, thisObj, onCrystalFullyLitEvents, "CrystalFullyLitEvents")
    SetSoundBifrostActive()
  elseif data == 3 then
    print("Temporal Crystal State 3")
    nestedFX:JumpAnimToFrame(0)
    nestedFX:PlayAnimToFrame(20)
    nestedFX:Show()
    SetSoundBifrostActive()
  else
    DisableTemporalObject()
    fullyLitMesh:Hide()
    normalLight:PauseAnim()
    normalLight:Hide()
    defaultLight:Show()
    defaultLight:PlayAnimCycle()
    shadowCastingLight:PauseAnim()
    shadowCastingLight:Hide()
    fullyLitMesh:PauseAnim()
    SetSoundBifrostInactive()
  end
end
function SetCrystalVisualState(data)
  if data == 0 then
    if temporalObject ~= nil then
      temporalObject:Hide()
    end
  elseif data == 1 then
    if temporalObject ~= nil then
      temporalObject:Hide()
    end
  elseif data == 2 and temporalObject ~= nil then
    temporalObject:Show()
  end
end
function SetActive(active)
  crystalActive = active
end
function Enable()
  enabled = true
end
function Disable()
  enabled = false
end
function HideObjectCollision()
  thisObj:HideCollision()
end
function ShowObjectCollision()
  thisObj:ShowCollision()
end
function CrystalFXPeaked(_, _, crystalFX)
  EnableTemporalObject()
  nestedFX:ClearAllAnimCallbacks()
  nestedFX:PlayAnimToFrame(50)
end
function DisableTemporalObject()
  if temporalObject ~= nil and temporalObject ~= "" then
    if temporalObject.LuaObjectScript and temporalObject.LuaObjectScript.IsTemporalObject then
      temporalObject.LuaObjectScript.TurnTemporalObjectOff()
    else
      for _, childObj in pairs(temporalObject.Descendants) do
        print("Disabling Temporal object child..", childObj)
        if childObj.LuaObjectScript and childObj.LuaObjectScript.IsTemporalObject then
          childObj.LuaObjectScript.TurnTemporalObjectOff(TOTurnedOff)
          bridgeCount = bridgeCount + 1
        else
          childObj:HideCollision()
          childObj:Hide()
        end
      end
    end
    if bridgeCount <= 0 then
      temporalObject:HideCollision()
      temporalObject:Hide()
    end
    print("Disabling Temporal Object..", temporalObject)
  end
end
function EnableTemporalObject()
  if temporalObject ~= nil and temporalObject ~= "" then
    if temporalObject.LuaObjectScript and temporalObject.LuaObjectScript.IsTemporalObject then
      temporalObject.LuaObjectScript.TurnTemporalObjectOn()
    else
      for _, childObj in pairs(temporalObject.Descendants) do
        print("Enabling Temporal object child..", childObj)
        if childObj.LuaObjectScript and childObj.LuaObjectScript.IsTemporalObject then
          childObj.LuaObjectScript.TurnTemporalObjectOn()
        else
          childObj:ShowCollision()
          childObj:Show()
        end
      end
      temporalObject:ShowCollision()
      temporalObject:Show()
    end
    print("Enabling Temporal Object..", temporalObject)
  end
end
function SetTemporalObject(newTemporalObject)
  temporalObject = newTemporalObject
end
function SetSocketed(newState)
  socketed = newState
  if socketed then
    print("JUST GOT SOCKETED --CRYSTAL")
    SetCrystalObjectStates(1)
  else
    print("JUST GOT UnSOCKETED --CRYSTAL")
    SetCrystalObjectStates(0)
  end
end
function TOTurnedOff()
  bridgesOff = bridgesOff + 1
  if bridgesOff >= bridgeCount then
    temporalObject:Hide()
    temporalObject:HideCollision()
  end
end
function OnSaveCheckpoint(level, obj)
  print("Crystal  - Saving")
  return {crystalActive = crystalActive, socketed = socketed}
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  crystalActive = savedInfo.crystalActive
  socketed = savedInfo.socketed
  print("Crystal - Restore Checkpoint", crystalActive, socketed)
  if crystalActive then
    SetCrystalObjectStates(2)
  elseif not crystalActive and socketed then
    SetCrystalObjectStates(1)
  else
    SetCrystalObjectStates(0)
  end
end
local soundEmitter, soundEmitterName
local SNDBifrostActiveLP = "SND_MAG_Temporal_Light_Torches_Active_LP"
local SNDBifrostInactiveLP = "SND_MAG_Temporal_Light_Torches_Inactive_LP"
local SNDBifrostPulse = "SND_MAG_Temporal_Light_Torches_Active_Hit_Sparks"
local SNDBifrostActivation = "SND_MAG_Temporal_Light_Torches_Active_LP_Start"
function SoundInit()
  soundEmitterName = thisObj:FindLuaTableAttribute("soundEmitterName")
  if soundEmitterName ~= nil and soundEmitterName ~= "" then
    soundEmitter = thisObj:FindSingleSoundEmitterByName(soundEmitterName)
  else
    soundEmitter = thisObj.SoundEmitters[1]
  end
end
function SetSoundBifrostActive()
  LD.StopRestartableSoundLoop(soundEmitter, SNDBifrostInactiveLP)
  LD.PlayRestartableSoundLoop(soundEmitter, SNDBifrostActiveLP)
end
function SetSoundBifrostInactive()
  LD.StopRestartableSoundLoop(soundEmitter, SNDBifrostActiveLP)
  LD.PlayRestartableSoundLoop(soundEmitter, SNDBifrostInactiveLP)
end
function PlayLightPulseSound()
  LD.PlaySound(soundEmitter, SNDBifrostPulse)
end
function PlaySoundActivateCrystal()
  LD.PlaySound(soundEmitter, SNDBifrostActivation)
end
