local mpicon = require("ui.mpicon")
local monitors = require("level.MonitorLibrary")
uiCalls = require("ui.uicalls")
local DragonHealthMonitor, dragonCreature, BossEncounter, dragonPuppeteer, heroPuppeteer, sonPuppeteer, sindriPuppeteer
local hudVisToggle = true
local pickupName = "EarthDragon_MetersTEMP"
local isFinaleCameraReady = false
local squareButtonMonitor
local SetupBossEncounter = function(bossEncounter)
  BossEncounter = bossEncounter
end
local stateTable = {
  GrabMelee = 0,
  BossStage_Pos1_Breath = 1,
  BossStage_Pos1_Stun = 2,
  BossStage_Pos3_Melee = 3,
  BossStage_Pos3_Breath = 4,
  BossStage_Pos3_Stun = 5,
  BossStage_Pos2_Melee = 6,
  BossStage_Pos2_Breath = 7,
  BossStage_Pos2_Stun = 8,
  BossStage_TugWar_Pos02_Melee = 9,
  BossStage_TugWar_Pos02_Breath = 10,
  BossStage_TugWar_Pos02_Stun = 11
}
local HealthRestore = {
  GrabMelee = 2000,
  BossStage_Pos1_Breath = 1900,
  BossStage_Pos1_BombFaceRegen = 1800,
  BossStage_Pos1_Stun = 1700,
  BossStage_Pos3_Melee = 1600,
  BossStage_Pos3_BombFaceRegen = 1400,
  BossStage_Pos3_Stun = 1300,
  BossStage_Pos2_Melee = 1200,
  BossStage_Pos2_BombFaceRegen = 1000,
  BossStage_Pos2_Stun = 900,
  BossStage_TugWar_Pos02_Melee = 800,
  BossStage_TugWar_Pos02_Stun = 500
}
local HealthToTransistion = {
  GrabMelee = 1850,
  BossStage_Pos1_Stun = 1600,
  BossStage_Pos3_Melee = 1500,
  BossStage_Pos3_Stun = 1200,
  BossStage_Pos2_Melee = 1100,
  BossStage_Pos2_Stun = 800,
  BossStage_TugWar_Pos02_Melee = 700,
  BossStage_TugWar_Pos02_Stun = 400
}
function FindEarthDragon()
  if dragonCreature == nil then
    for creature in game.Creature.IterateAllCreatures() do
      if creature:GetName() == "earthdragon00" then
        dragonCreature = creature
        break
      end
    end
  end
  return dragonCreature
end
function FindSindri()
  local sindri
  for creature in game.Creature.IterateAllCreatures() do
    if creature:GetName() == "sindri00" then
      sindri = creature
      break
    end
  end
  return sindri
end
function SyncDragonToArena(level, goSpawnerName, syncName, dragonStateData, goRefJointName)
  local l_currentState = BossEncounter:GetActiveStateName()
  local l_branch = dragonStateData[l_currentState].BRAname
  local l_hero, l_heroBRA, l_son, l_sonBRA, l_propObj, l_propName, l_propAnim, l_propObj02, l_propName02, l_propAnim02, l_heroPuppeteer, l_sonPuppeteer
  local slaveTable = {}
  l_propAnim = dragonStateData[l_currentState].propAnim
  l_propName = dragonStateData[l_currentState].propName
  if l_propAnim ~= nil then
    l_propObj = level:FindSingleGameObject(l_propName).Child
    table.insert(slaveTable, {Slave = l_propObj, Anim = l_propAnim})
  end
  l_propAnim02 = dragonStateData[l_currentState].propAnim02
  l_propName02 = dragonStateData[l_currentState].propName02
  if l_propAnim02 ~= nil then
    l_propObj02 = level:FindSingleGameObject(l_propName02).Child
    table.insert(slaveTable, {Slave = l_propObj02, Anim = l_propAnim02})
  end
  l_heroBRA = dragonStateData[l_currentState].heroBRA
  if l_heroBRA ~= nil then
    l_heroPuppeteer = game.Puppeteer.NewForce(level:GetGameObject(goSpawnerName), syncName, game.Player:FindPlayer())
    table.insert(slaveTable, {Slave = l_heroPuppeteer, Branch = l_heroBRA})
  end
  l_sonBRA = dragonStateData[l_currentState].sonBRA
  if l_sonBRA ~= nil then
    l_sonPuppeteer = game.Puppeteer.NewForce(level:GetGameObject(goSpawnerName), syncName, game.AI.FindSon())
    table.insert(slaveTable, {Slave = l_sonPuppeteer, Branch = l_sonBRA})
  end
  if dragonPuppeteer == nil then
    dragonPuppeteer = game.Puppeteer.NewForce(level:GetGameObject(goSpawnerName), syncName, FindEarthDragon())
  end
  dragonPuppeteer:Clear()
  if l_heroPuppeteer ~= nil then
    l_heroPuppeteer:AcceptSync()
  end
  if l_sonPuppeteer ~= nil then
    l_sonPuppeteer:AcceptSync()
  end
  dragonPuppeteer:Sync(l_branch, true, slaveTable, goRefJointName)
  dragonPuppeteer:OnComplete(function()
    if dragonPuppeteer ~= nil then
      dragonPuppeteer:Clear()
      dragonPuppeteer = nil
    end
    l_heroPuppeteer = nil
    l_sonPuppeteer = nil
  end)
end
local DragonSyncCompleted = function(stage)
  print("dragon sync completed, stage ", stage)
  if dragonPuppeteer ~= nil then
    dragonPuppeteer:Clear()
    dragonPuppeteer = nil
  end
  heroPuppeteer = nil
  sonPuppeteer = nil
  sindriPuppeteer = nil
end
local SyncOnlyDragonToArena = function(synchObject, syncBranch, dragonActor, synchJoint, stage, slaveData)
  if dragonPuppeteer ~= nil then
    dragonPuppeteer:Clear()
    dragonPuppeteer = nil
  end
  heroPuppeteer = nil
  sonPuppeteer = nil
  sindriPuppeteer = nil
  local slaveTable = {}
  if slaveData ~= nil then
    if slaveData.syncHero then
      heroPuppeteer = game.Puppeteer.NewForce(synchObject, stage .. "_player", game.Player.FindPlayer())
      heroPuppeteer:AcceptSync()
      local heroTable = {Slave = heroPuppeteer, Branch = syncBranch}
      table.insert(slaveTable, heroTable)
    end
    if slaveData.syncSon then
      sonPuppeteer = game.Puppeteer.NewForce(synchObject, stage .. "_son", game.AI.FindSon())
      sonPuppeteer:AcceptSync()
      local sonTable = {Slave = sonPuppeteer, Branch = syncBranch}
      table.insert(slaveTable, sonTable)
    end
    if slaveData.syncSindri then
      sindriPuppeteer = game.Puppeteer.NewForce(synchObject, stage .. "_sindri", FindSindri())
      sindriPuppeteer:AcceptSync()
      local sindriTable = {Slave = sindriPuppeteer, Branch = syncBranch}
      table.insert(slaveTable, sindriTable)
    end
    if slaveData.prop1 ~= nil then
      local propTable = {
        Slave = slaveData.prop1,
        Anim = slaveData.propAnim
      }
      table.insert(slaveTable, propTable)
    end
    if slaveData.prop2 ~= nil then
      local propTable = {
        Slave = slaveData.prop2,
        Anim = slaveData.propAnim
      }
      table.insert(slaveTable, propTable)
    end
  end
  dragonPuppeteer = game.Puppeteer.NewForce(synchObject, "Dragon Sync " .. stage, dragonActor)
  dragonPuppeteer:Sync(syncBranch, true, slaveTable, synchJoint)
  dragonPuppeteer:OnComplete(function()
    DragonSyncCompleted(stage)
  end)
end
function ResetMomentum()
  local l_player = game.Player.FindPlayer()
  l_player:CallScript("MomentumClear")
end
function DragonHealthMonitor_OnUpdate()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor == nil then
    return
  end
  local l_currentState_str = BossEncounter:GetActiveStateName()
  local l_currentState = stateTable[l_currentState_str]
  local l_dragonHealth = l_dragonActor:MeterGetValue("DragonBossHealth")
  local l_dragonShield = l_dragonActor:MeterGetValue("DragonBossShield")
  local l_dragonHiddenHealth = l_dragonActor:MeterGetValue("DragonBossHealth_Hidden")
  if l_currentState == stateTable.GrabMelee then
    if l_dragonHiddenHealth < HealthToTransistion.GrabMelee then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.GrabMelee)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.GrabMelee)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_Pos1_Stun then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_Pos1_Stun then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_Pos1_Stun)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_Pos1_Stun)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_Pos3_Melee then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_Pos3_Melee then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_Pos3_Melee)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_Pos3_Melee)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_Pos3_Stun then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_Pos3_Stun then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_Pos3_Stun)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_Pos3_Stun)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_Pos2_Melee then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_Pos2_Melee then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_Pos2_Melee)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_Pos2_Melee)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_Pos2_Stun then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_Pos2_Stun then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_Pos2_Stun)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_Pos2_Stun)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_TugWar_Pos02_Melee then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_TugWar_Pos02_Melee then
      l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthToTransistion.BossStage_TugWar_Pos02_Melee)
      l_dragonActor:MeterSetValue("DragonBossHealth", HealthToTransistion.BossStage_TugWar_Pos02_Melee)
      BossEncounter:ForwardState()
      return
    end
  elseif l_currentState == stateTable.BossStage_TugWar_Pos02_Stun then
    if l_dragonHiddenHealth < HealthToTransistion.BossStage_TugWar_Pos02_Stun and squareButtonMonitor == nil then
      mpicon.level.Create(GameObjects.FinaleInteractLocation, "DRAGON_FINALE_INTERACT")
      squareButtonMonitor = monitors.CreateSquareButtonMonitor()
      squareButtonMonitor:OnButtonDown(function()
        mpicon.level.Off(GameObjects.FinaleInteractLocation, "DRAGON_FINALE_INTERACT")
        BossEncounter:ForwardState()
        isFinaleCameraReady = false
        squareButtonMonitor:Stop()
        squareButtonMonitor = nil
      end)
      GameObjects.throwablecrystalspawner2.LuaObjectScript.InteractDisable()
      if hudVisToggle then
        isFinaleCameraReady = true
        ToggleMeterBarVis(false)
        ForceAllHudOff()
        hudVisToggle = false
      end
      return
    end
  elseif l_dragonShield <= 0 and (l_currentState == stateTable.BossStage_TugWar_Pos02_Breath or l_currentState == stateTable.BossStage_Pos3_Breath or l_currentState == stateTable.BossStage_Pos2_Breath or l_currentState == stateTable.BossStage_Pos1_Breath) then
    l_dragonActor:PickupSetStage("EarthDragon_HitBombFaceCounter", 2)
    l_dragonActor:TriggerMoveEvent("bombFace")
    return
  end
end
function InitMetersForStartOfArena()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos1_Breath)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos1_Breath)
  end
end
function RegenBombFaceDamage_FromPos01Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos1_BombFaceRegen)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos1_BombFaceRegen)
  end
end
function InitMetersForStartOfPos01Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos1_Stun)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos1_Stun)
  end
end
function InitMetersForStartOfPos03Melee()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos3_Melee)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos3_Melee)
  end
end
function RegenBombFaceDamage_FromPos03Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos3_BombFaceRegen)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos3_BombFaceRegen)
  end
end
function InitMetersForStartOfPos03Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos3_Stun)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos3_Stun)
  end
end
function InitMetersForStartOfPos02Melee()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos2_Melee)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos2_Melee)
  end
end
function RegenBombFaceDamage_FromPos02Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos2_BombFaceRegen)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos2_BombFaceRegen)
  end
end
function InitMetersForStartOfPos02Stun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_Pos2_Stun)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_Pos2_Stun)
  end
end
function InitMetersForStartOfTugOfWar()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_TugWar_Pos02_Melee)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_TugWar_Pos02_Melee)
  end
end
function InitMetersForStartOfTugOfWarStun()
  local l_dragonActor = FindEarthDragon()
  if l_dragonActor ~= nil then
    l_dragonActor:MeterSetValue("DragonBossHealth", HealthRestore.BossStage_TugWar_Pos02_Stun)
    l_dragonActor:MeterSetValue("DragonBossHealth_Hidden", HealthRestore.BossStage_TugWar_Pos02_Stun)
  end
end
local bossHealthBarOn = false
function ToggleMeterBarVis(toggle)
  local l_dragonActor = FindEarthDragon()
  if toggle == nil or toggle then
    if bossHealthBarOn == false then
      mpicon.level.Create(l_dragonActor:GetGameObject(), "EARTHDRAGONBOSS_HEALTH_BAR")
      mpicon.level.SetTextObjectText(l_dragonActor, "EARTHDRAGONBOSS_HEALTH_BAR", "enemyLevel", "")
      mpicon.level.SetTextObjectText(l_dragonActor, "EARTHDRAGONBOSS_HEALTH_BAR", "bossName", "[MSG:" .. 38191 .. "]")
      mpicon.level.SetTextObjectText(l_dragonActor, "EARTHDRAGONBOSS_HEALTH_BAR", "icon", "\198\164")
      bossHealthBarOn = true
    end
  else
    mpicon.level.Off(l_dragonActor:GetGameObject(), "EARTHDRAGONBOSS_HEALTH_BAR")
    bossHealthBarOn = false
  end
end
function ForceAllHudOff()
  uiCalls.UI_Event_Force_Combat_HUD_Off()
  uiCalls.UI_Event_TurnOffDesignerMessage()
  game.Compass.SetDesignerForcedHide(true)
end
function ForceAllHudOn()
  uiCalls.UI_Event_Force_Combat_HUD_On()
  game.Compass.SetDesignerForcedHide(false)
end
function ForceAllHudOnNoCompass()
  uiCalls.UI_Event_Force_Combat_HUD_On()
  game.Compass.SetDesignerForcedHide(true)
end
function FinaleCameraReady()
  if isFinaleCameraReady then
    return true
  end
end
function DamageHealthBar()
  local l_dragonActor = FindEarthDragon()
  mpicon.level.PlayAnimation(l_dragonActor:GetGameObject(), "EARTHDRAGONBOSS_HEALTH_BAR", 0, "bossHealthBar_Damaged", nil, nil, nil, nil)
end
return {
  SetupBossEncounter = SetupBossEncounter,
  FindEarthDragon = FindEarthDragon,
  FindSindri = FindSindri,
  SyncDragonToArena = SyncDragonToArena,
  SyncOnlyDragonToArena = SyncOnlyDragonToArena,
  DragonHealthMonitor_OnUpdate = DragonHealthMonitor_OnUpdate,
  HealthRestore = HealthRestore,
  ToggleMeterBarVis = ToggleMeterBarVis,
  DamageHealthBar = DamageHealthBar,
  InitMetersForStartOfArena = InitMetersForStartOfArena,
  InitMetersForStartOfPos03Melee = InitMetersForStartOfPos03Melee,
  InitMetersForStartOfPos02Melee = InitMetersForStartOfPos02Melee,
  InitMetersForStartOfTugOfWar = InitMetersForStartOfTugOfWar,
  InitMetersForStartOfPos01Stun = InitMetersForStartOfPos01Stun,
  InitMetersForStartOfPos03Stun = InitMetersForStartOfPos03Stun,
  InitMetersForStartOfPos02Stun = InitMetersForStartOfPos02Stun,
  InitMetersForStartOfTugOfWarStun = InitMetersForStartOfTugOfWarStun,
  RegenBombFaceDamage_FromPos01Stun = RegenBombFaceDamage_FromPos01Stun,
  RegenBombFaceDamage_FromPos03Stun = RegenBombFaceDamage_FromPos03Stun,
  RegenBombFaceDamage_FromPos02Stun = RegenBombFaceDamage_FromPos02Stun,
  ResetMomentum = ResetMomentum,
  ForceAllHudOn = ForceAllHudOn,
  ForceAllHudOff = ForceAllHudOff,
  ForceAllHudOnNoCompass = ForceAllHudOnNoCompass,
  FinaleCameraReady = FinaleCameraReady
}
