local LD = require("design.LevelDesignLibrary")
local timers = require("level.timer")
local EC = require("design.Encounter")
local checkpoint = require("level.checkpoint")
local monitors = require("level.MonitorLibrary")
local uiCalls = require("ui.uicalls")
local EncounterSM = require("boss.statemachine")
local thisLevel, player, Area_1_Encounter_1, Area_1_Encounter_2, Area_1_Encounter_3, Area_1_Encounter_4, Area_1_Encounter_5, Area_1_Encounter_6
local A1_Challenge_1 = false
local A1_E1_C = false
local A1_E2_C = false
local A1_E3_C = false
local A1_Encounters = {}
local A1_Encounters_Index = 1
Challenge_Message = "NULL MESSAGE"
local Challenge_1 = EncounterSM:AddStage("Time Attack", true)
local Challenge_2 = EncounterSM:AddStage("Enemies need to be killed in quick succession or else they revive", true)
local Challenge_3 = EncounterSM:AddStage("GOLD 1", true)
local Time_Attack_Started = false
local ecTimer, ec_TimeRequirement, timeRemaining
local Challenge_Duration_Time = 180
local Challenge_KillCount = 25
local ONE_HIT = false
local OneHitCallMonitor, requiredNumKilled
local KillCount = 20
local DraugrChallenge_KillCount = KillCount
local area1timedMus = false
function OnScriptLoaded(level, obj)
  thisLevel = level
  player = game.Player.FindPlayer()
  Bronze_Challenge_Arena_1_Fight()
  Silver_Challenge_Arena_1_Fight()
  Gold_Challenge_Arena_1_Fight()
end
function OnStart(level, obj)
end
function OnUpdate(level)
  if Time_Attack_Started then
    Encounter_Timer()
  end
  if ONE_HIT and not player:PickupIsAcquired("MuspelheimSingleHitChallenge") then
    EventFailed_OneHit()
  end
  if Area_1_Encounter_2 ~= nil and Area_1_Encounter_2:IsRunning(2) and not player:PickupIsAcquired("MuspelheimSingleHitChallenge") and Area_1_Encounter_2:GetNumEnemiesAlive(2) == 1 and player:IsPlayingMove("MOV_CSRageGrabJotunnExitWin") then
    Area_1_Encounter_2:StopInfiniteSpawning(2)
  end
end
function OnUseWorld(level, obj)
end
function OnSaveCheckpoint(level)
  return {
    levelstate = checkpoint.Save(),
    temp_Start_A1_E1_C = A1_E1_C,
    temp_Start_A1_E2_C = A1_E2_C,
    temp_Start_A1_E3_C = A1_E3_C
  }
end
function OnRestoreCheckpoint(level, obj, savedInfo)
  checkpoint.Restore(savedInfo.levelstate)
  A1_E1_C = savedInfo.temp_Start_A1_E1_C
  A1_E2_C = savedInfo.temp_Start_A1_E2_C
  A1_E3_C = savedInfo.temp_Start_A1_E3_C
end
function Challenge_1:OnEnter(level)
  Area_1_Encounter_1:Reset()
  Area_1_Encounter_1:Start()
  A1_Encounters_Index = 1
end
function Challenge_1:OnExit(level)
  Area_1_Encounter_1:DespawnEnemies()
  Area_1_Encounter_1:Stop()
  OneHitCallMonitor:Stop()
end
function Challenge_2:OnEnter(level)
  Area_1_Encounter_2:Reset()
  Area_1_Encounter_2:DespawnEnemies()
  Area_1_Encounter_2:Stop()
  A1_Encounters_Index = 2
end
function Challenge_2:OnExit(level)
  Area_1_Encounter_2:DespawnEnemies()
  Area_1_Encounter_2:Stop()
end
function Challenge_3:OnEnter(level)
  Area_1_Encounter_3:Reset()
  Area_1_Encounter_3:DespawnEnemies()
  Area_1_Encounter_3:Stop()
end
function Challenge_3:OnExit(level)
  Area_1_Encounter_3:DespawnEnemies()
  Area_1_Encounter_3:Stop()
end
function Challenge_Finished()
  LD.CallFunctionAfterDelay(function()
    uiCalls.UI_Event_TurnOffDesignerMessage()
  end, 4.3)
end
function Start_Area_1_Encounter_1()
  LD.CallFunctionAfterDelay(function()
    A1_Encounters[A1_Encounters_Index]:Start()
    Area_1_Encounter_1:Start()
  end, _G.GetPreEncounterCooldown())
end
function Start_Area_1_Encounter_2()
  uiCalls.UI_Event_TurnOffDesignerMessage()
  LD.CallFunctionAfterDelay(function()
    Area_1_Encounter_2:Start()
  end, _G.GetPreEncounterCooldown())
end
function Start_Area_1_Encounter_3()
  LD.CallFunctionAfterDelay(function()
    if Area_1_Encounter_3:IsComplete() then
      Area_1_Encounter_3:Restart()
    else
      Area_1_Encounter_3:Start()
    end
  end, _G.GetPreEncounterCooldown())
end
local Arena_1_OnEncounterComplete = function()
  A1_Encounters_Index = A1_Encounters_Index + 1
  if A1_Encounters[A1_Encounters_Index] ~= nil then
    A1_Encounters[A1_Encounters_Index]:Start()
  else
    Challenge_Finished()
  end
end
local Area_1_OnEncounterFailed = function()
  _G.MSP_Despawn_Enemy_VFX(A1_Encounters[A1_Encounters_Index])
  A1_Encounters[A1_Encounters_Index]:Reset()
  A1_Encounters[A1_Encounters_Index]:Stop()
  GameObjects.Muspelheim_Arena_Marker_01.LuaObjectScript.ChallengeFailed()
end
function Bronze_Challenge_Arena_1_Fight()
  Area_1_Encounter_1 = EC.NewEncounter(thisLevel, "[Arena 1]EC:1 - Bronze - Time Attack", {
    CheckpointOnComplete = true,
    spawnWad = "Msp110_Arena01"
  })
  Area_1_Encounter_1:AddWave({
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 2,
      initialSpawnCooldown = {0.01, 0.09},
      maxActive = 3,
      totalSpawns = 3,
      spawnCooldown = 3,
      powerLevel = 3
    }
  })
  Area_1_Encounter_1:AddWave({
    powerLevel = 3,
    {
      spawners = "Draugr_L_SFG",
      spawnLocators = "A1_Loc_O_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 3
    },
    {
      spawners = "Draugr_P_SFG",
      spawnLocators = "A1_Loc_BackEdge_1*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 0.8
    },
    {
      spawners = "Draugr_P_SFG",
      spawnLocators = "A1_Loc_BackEdge_6*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 5
    }
  })
  Area_1_Encounter_1:AddWave({
    {
      spawners = "H_Draugr_N_SFG",
      spawnLocators = "A1_Loc_O_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 2,
      initialSpawnCooldown = 2,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 8,
      powerLevel = 2
    }
  })
  Area_1_Encounter_1:AddWave({
    requireCompletionOfAllPriorWaves = true,
    {
      spawners = "SH_Draugr_N_SFG",
      spawnLocators = "A1_Loc_O_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 10,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 5,
      powerLevel = 4
    },
    {
      spawners = "SH_Draugr_N_SFG",
      spawnLocators = "A1_Loc_O_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 3,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 5,
      powerLevel = 3
    },
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_O_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 2,
      initialSpawnCooldown = 2,
      maxActive = 3,
      totalSpawns = 3,
      spawnCooldown = 8,
      powerLevel = 3
    }
  })
  Area_1_Encounter_1:OnEnemyDeath(function()
    Area_1_Encounter_1:StartWave(4)
  end, {wave = 3, count = 2})
  Area_1_Encounter_1:OnEnemyDeath(function()
    Challenge_KillCount = Challenge_KillCount - 1
    DraugrChallenge_KillCount = DraugrChallenge_KillCount - 1
  end)
  Area_1_Encounter_1:OnStart(function()
    Start_Timer()
    Challenge_KillCount = 15
  end)
  Area_1_Encounter_1:OnCombatStart(function()
    game.Audio.StartMusic("SND_MX_MSP_trial_11_start")
    area1timedMus = false
  end)
  Area_1_Encounter_1:OnComplete(function()
    uiCalls.DisableMechanicText()
    Time_Attack_Started = false
    ecTimer:Stop()
    ecTimer = nil
    Area1TimedMusic()
  end)
  table.insert(A1_Encounters, Area_1_Encounter_1)
end
function AddOnCompleteCallback(encounterIndex, callback)
  if A1_Encounters and A1_Encounters[encounterIndex] then
    A1_Encounters[encounterIndex]:OnComplete(callback)
  end
end
function Silver_Challenge_Arena_1_Fight()
  Area_1_Encounter_2 = EC.NewEncounter(thisLevel, "[Arena 1]EC:2 - Silver - Death Defiers", {
    CheckpointOnComplete = true,
    spawnWad = "Msp110_Arena01",
    StartMusic = "SND_MX_MSP_trial_21_start",
    StopMusic = "SND_MX_MSP_trial_21_win"
  })
  Area_1_Encounter_2:AddWave({
    powerLevel = 3,
    timeBetweenWaves = 2.2,
    {
      spawners = "SH_Draugr_L_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 13
    },
    {
      spawners = "Draugr_P_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1.8,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 13
    },
    {
      spawners = "H_Draugr_B_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 2.3,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 13
    }
  })
  Area_1_Encounter_2:AddWave({
    timeBetweenWaves = 4,
    {
      spawners = "Jotunn_SCS",
      spawnLocators = "A1_Loc_I_MiddleGate_1",
      spawnWad = "Msp110_Arena01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 10,
      powerLevel = 3
    },
    {
      spawners = "Witch_P_SFG",
      spawnLocators = "A1_Loc_BackEdge_5*",
      spawnWad = "Msp110_Arena01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 10,
      powerLevel = 3
    }
  })
  Area_1_Encounter_2:AddWave({
    {
      spawners = "Wolf_N_SFG",
      spawnLocators = "A1_Loc_I*",
      spawnWad = "Msp110_Arena01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 3,
      initialSpawnCooldown = 2,
      maxActive = 3,
      totalSpawns = 3,
      spawnCooldown = 15,
      powerLevel = 3
    },
    {
      spawners = "Crawler_N_SFG",
      spawnLocators = "A1_Loc_BackEdge_1*",
      spawnWad = "Msp110_Arena01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 1,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 12,
      powerLevel = 3
    },
    {
      spawners = "Crawler_N_SFG",
      spawnLocators = "A1_Loc_BackEdge_6*",
      spawnWad = "Msp110_Arena01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 2,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 12,
      powerLevel = 4
    }
  })
  Area_1_Encounter_2:OnEnemyDeath(function()
    uiCalls.EnableMechanicText(37910, {
      Area_1_Encounter_2:GetNumEnemiesAlive()
    })
  end)
  Area_1_Encounter_2:OnEnemySpawn(function()
    uiCalls.EnableMechanicText(37910, {
      Area_1_Encounter_2:GetNumEnemiesAlive()
    })
  end)
  Area_1_Encounter_2:OnEnemyDeath(function()
    Check_Death_Defiers(Area_1_Encounter_2, 1)
  end, {wave = 1})
  Area_1_Encounter_2:OnEnemyDeath(function()
    Check_Death_Defiers(Area_1_Encounter_2, 2)
  end, {wave = 2})
  Area_1_Encounter_2:OnEnemyDeath(function()
    Check_Death_Defiers(Area_1_Encounter_2, 3)
  end, {wave = 3})
  Area_1_Encounter_2:OnStart(function()
    Area_1_Encounter_2:StartInfiniteSpawning(1)
  end, 1)
  Area_1_Encounter_2:OnStart(function()
    Area_1_Encounter_2:StartInfiniteSpawning(2)
  end, 2)
  Area_1_Encounter_2:OnStart(function()
    Area_1_Encounter_2:StartInfiniteSpawning(3)
  end, 3)
  Area_1_Encounter_2:OnComplete(function()
    uiCalls.EnableMechanicText("[MSG:38167]")
  end, 1)
  Area_1_Encounter_2:OnComplete(function()
    uiCalls.EnableMechanicText("[MSG:38167]")
  end, 2)
  Area_1_Encounter_2:OnComplete(function()
    uiCalls.DisableMechanicText()
    Challenge_Finished()
  end, 3)
  table.insert(A1_Encounters, Area_1_Encounter_2)
end
function EventFailed_OneHit()
  uiCalls.UI_Event_TurnOffDesignerMessage()
  uiCalls.SendBottomDesignerMessage({Text = 37911, Critical = true})
  Area_1_OnEncounterFailed()
end
function Gold_Challenge_Arena_1_Fight()
  Area_1_Encounter_3 = EC.NewEncounter(thisLevel, "[Arena 1]EC:3 - Gold Fire & Blood", {CheckpointOnComplete = true})
  Area_1_Encounter_3:AddWave({
    timeBetweenWaves = 2.15,
    requiredWaveCompletion = 50,
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 2,
      totalSpawns = 3,
      spawnCooldown = 0.5,
      powerLevel = 6
    },
    {
      spawners = "SH_Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 2,
      powerLevel = 5
    },
    {
      spawners = "SH_Draugr_L_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 3.4,
      powerLevel = 5
    }
  })
  Area_1_Encounter_3:AddWave({
    timeBetweenWaves = 3.32,
    requiredWaveCompletion = 50,
    requireCompletionOfAllPriorWaves = true,
    {
      spawners = "E_Wulver_S_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Gold_01",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 1,
      powerLevel = 6
    },
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 2.4,
      powerLevel = 5
    },
    {
      spawners = "E_Wulver_S_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Gold_01",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 8,
      powerLevel = 5
    }
  })
  Area_1_Encounter_3:AddWave({
    requireCompletionOfAllPriorWaves = true,
    timeBetweenWaves = 3.32,
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 1.2,
      powerLevel = 6
    },
    {
      spawners = "Draugr_N_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 2,
      powerLevel = 6
    }
  })
  Area_1_Encounter_3:AddWave({
    {
      spawners = "Draugr_L_SFG",
      spawnLocators = "A1_Loc_I_*",
      spawnWad = "Msp100_Base",
      useSpawnLocatorsOnly = true,
      maxActive = 2,
      totalSpawns = 2,
      spawnCooldown = 2.4,
      powerLevel = 5
    },
    {
      spawners = "Golem_S_SFG",
      spawnLocators = "A1_Loc_I_MiddleGate_1*",
      spawnWad = "Msp100_Gold_01",
      useSpawnLocatorsOnly = true,
      initialSpawnAmount = 1,
      initialSpawnCooldown = 20,
      maxActive = 1,
      totalSpawns = 1,
      spawnCooldown = 8,
      powerLevel = 6
    }
  })
  Area_1_Encounter_3:OnStart(function()
    DraugrChallenge_KillCount = Area_1_Encounter_3:GetTotalSpawns()
    One_Hit_Challenge()
    uiCalls.EnableMechanicText(37922, {DraugrChallenge_KillCount})
  end)
  Area_1_Encounter_3:OnCombatStart(function()
    game.Audio.StartMusic("SND_MX_MSP_trial_31_start")
  end)
  Area_1_Encounter_3:OnEnemySpawn(function(enemy)
    timers.StartLevelTimer(0.5, function()
      if enemy ~= nil then
        enemy:ForceMove("BRA_SetDropHealthFlag_On")
      end
    end)
  end, {wave = 1, element = 3})
  Area_1_Encounter_3:OnEnemyDeath(function()
    if DraugrChallenge_KillCount == nil then
      return
    end
    DraugrChallenge_KillCount = DraugrChallenge_KillCount - 1
    if 0 < DraugrChallenge_KillCount and 0 < KillCount then
      uiCalls.EnableMechanicText(37922, {DraugrChallenge_KillCount})
    end
  end)
  Area_1_Encounter_3:OnComplete(function()
    uiCalls.DisableMechanicText()
    ONE_HIT = false
    Clear_One_Hit_Challenge()
    game.Audio.StartMusic("SND_MX_MSP_trial_31_win")
  end)
  table.insert(A1_Encounters, Area_1_Encounter_3)
end
function One_Hit_Challenge()
  ONE_HIT = true
  player:PickupAcquire("MuspelheimSingleHitChallenge")
  player:PickupActivate("MuspelheimSingleHitChallenge")
end
function Clear_One_Hit_Challenge()
  uiCalls.UI_Event_ClearAllDesignerMessages()
  player:PickupDeactivate("MuspelheimSingleHitChallenge")
  player:PickupRelinquish("MuspelheimSingleHitChallenge")
end
function EventFailed_OneHit()
  ONE_HIT = false
  timers.StartLevelTimer(1.2, function()
    uiCalls.SendBottomDesignerMessage({Text = 37911, Critical = true})
  end)
  DraugrChallenge_KillCount = nil
  timers.StartLevelTimer(1, function()
    uiCalls.DisableMechanicText()
    DraugrChallenge_KillCount = KillCount
  end)
  _G.MSP_Despawn_Enemy_VFX(Area_1_Encounter_3)
  Area_1_Encounter_3:Reset()
  Area_1_Encounter_3:Stop()
  GameObjects.Muspelheim_Arena_Marker_01.LuaObjectScript.ChallengeFailed()
  game.Audio.StartMusic("SND_MX_MSP_trial_31_fail")
end
function Check_Death_Defiers(encounter, wave)
  if encounter:GetNumEnemiesAlive(wave) == 0 then
    encounter:SetComplete(wave)
    encounter:StopInfiniteSpawning(wave)
  end
end
function Encounter_Timer()
  timeRemaining = math.floor(ec_TimeRequirement - ecTimer.time)
  local seconds = timeRemaining % 60
  local minutes = (timeRemaining - seconds) / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
  uiCalls.EnableMechanicText(37907, {
    Challenge_KillCount,
    minutes,
    seconds
  })
end
function Start_Timer()
  local startDelay = 1
  Time_Attack_Started = true
  ec_TimeRequirement = Challenge_Duration_Time
  ecTimer = StartLevelTimer(ec_TimeRequirement, function()
    EventFailed_TimeElapsed()
  end)
  ecTimer:Stop()
  LD.CallFunctionAfterDelay(function()
    ecTimer:Start()
  end, startDelay)
  local seconds = ec_TimeRequirement % 60
  local minutes = ec_TimeRequirement / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
end
function EventFailed_TimeElapsed()
  uiCalls.DisableMechanicText()
  local seconds = Challenge_Duration_Time % 60
  local minutes = Challenge_Duration_Time / 60
  local Time_Text = string.format("%02d : %02d", minutes, seconds)
  timers.StartLevelTimer(1.2, function()
    uiCalls.SendBottomDesignerMessage({Text = 37911, Critical = true})
  end)
  _G.MSP_Despawn_Enemy_VFX(A1_Encounters[A1_Encounters_Index])
  A1_Encounters[A1_Encounters_Index]:Reset()
  A1_Encounters[A1_Encounters_Index]:Stop()
  timers.StartLevelTimer(1.2, function()
    GameObjects.Muspelheim_Arena_Marker_01.LuaObjectScript.ChallengeFailed()
  end)
  ecTimer:Stop()
  ecTimer:Reset()
  Time_Attack_Started = false
  area1_1MusFail()
end
function Area1TimedMusic()
  if area1timedMus == false then
    game.Audio.StartMusic("SND_MX_MSP_trial_11_win")
  end
end
function area1_1MusFail()
  game.Audio.StartMusic("SND_MX_MSP_trial_11_fail")
  area1timedMus = true
end
