class_name BattleSingleton extends Node

enum BattlePosition {
  LEFT_TOP_BACK,
  LEFT_TOP_FRONT,
  LEFT_MIDDLE_BACK,
  LEFT_MIDDLE_FRONT,
  LEFT_BOTTOM_BACK,
  LEFT_BOTTOM_FRONT,

  RIGHT_TOP_BACK,
  RIGHT_TOP_FRONT,
  RIGHT_MIDDLE_BACK,
  RIGHT_MIDDLE_FRONT,
  RIGHT_BOTTOM_BACK,
  RIGHT_BOTTOM_FRONT
}

static func isPositionRight(battlePos:BattlePosition) -> bool:
  return battlePos in [
    BattlePosition.RIGHT_TOP_BACK,
    BattlePosition.RIGHT_TOP_FRONT,
    BattlePosition.RIGHT_MIDDLE_BACK,
    BattlePosition.RIGHT_MIDDLE_FRONT,
    BattlePosition.RIGHT_BOTTOM_BACK,
    BattlePosition.RIGHT_BOTTOM_FRONT
  ]
  

# Battle State
var active:bool = false
var fighterMap:Dictionary[BattlePosition, BattleFighter] = {}
var battleCutscene:Cutscene = null

# Non-guarantees
var battleScene:BattleScene = null

# Signals
signal battleStarted
signal battleFightersChanged

func startBattle(params) -> void:
  assert(params.has('fighters'))
  assert(!active)

  # Get the cutscene (or create a default one).
  if params.has('cutscene'):
    battleCutscene = params['cutscene']
  else:
    battleCutscene = Cutscene.new()

  # Update fighters for each fighter scene.
  for pos in BattlePosition.values():
    var fighterOrNull = params['fighters'].get(pos, null)
    fighterMap[pos] = fighterOrNull

  # Initial cutscene elements. In future I may need to make this editable
  # somehow?
  battleCutscene.addCallable(BattleCutsceneAction.getPlayerDecisionCallable())

  # Emit signals
  active = true
  battleStarted.emit()
  battleFightersChanged.emit()

  # Start running the battle cutscene.
  if !battleCutscene.running:
    battleCutscene.start()# Should this await?

func getFighterAtPosition(battlePos:BattlePosition) -> BattleFighter:
  return fighterMap.get(battlePos, null)

func getPositionOfFighter(fighter:BattleFighter) -> BattlePosition:
  for pos in fighterMap.keys():
    if fighterMap[pos] == fighter:
      return pos
      
  assert(false)
  return BattlePosition.LEFT_TOP_BACK

func getEnemyPositions() -> Array[BattlePosition]:
  # Not sure if I'm going to have pincer attacks so for now just do it based on 
  # the fighter positions.
  var positions:Array[BattlePosition] = []
  for pos in BattlePosition.values():
    var fighter = getFighterAtPosition(pos)
    if fighter == null:
      continue
    if fighter.team != BattleFighter.FighterTeam.ENEMY:
      continue
    positions.append(pos)
  return positions

func getAllyPositions() -> Array[BattlePosition]:
  var positions:Array[BattlePosition] = []
  for pos in BattlePosition.values():
    var fighter = getFighterAtPosition(pos)
    if fighter == null:
      continue
    if fighter.team != BattleFighter.FighterTeam.ALLY:
      continue
    positions.append(pos)
  return positions
