class_name BattleFighter

enum Status {
  NORMAL,
  DEAD,
}

enum FighterTeam {
  ALLY,
  ENEMY
}

enum FighterController {
  PLAYER,
  AI
}

# Health
var health:int
var maxHealth:int
var mp:int
var maxMp:int
var status:Status

# Identity
var team:FighterTeam
var controller:FighterController

# Stats
var attack:int
var defense:int
var speed:int
var magic:int
var luck:int

# Equipment

# Moves
var movePrimary:BattleMove
var movesMagical:Array[BattleMove]
var movesAbility:Array[BattleMove]

# Signals
signal healthChanged(difference:int, crit:bool)
signal mpChanged(difference:int)
signal statusChanged(oldStatus:Status, newStatus:Status)

func _init(params:Dictionary) -> void:
  self.maxHealth = params.get('maxHealth', 100)
  self.maxMp = params.get('maxMp', 50)
  self.attack = params.get('attack', 10)
  self.defense = params.get('defense', 5)
  self.speed = params.get('speed', 5)
  self.magic = params.get('magic', 5)
  self.luck = params.get('luck', 1)
  self.team = params.get('team', FighterTeam.ENEMY)
  self.controller = params.get('controller', FighterController.PLAYER)
  self.movePrimary = params.get('movePrimary', null)
  if params.has('movesMagical'):
    movesMagical.append_array(params['movesMagical'])
  if params.has('movesAbility'):
    movesAbility.append_array(params['movesAbility'])

  self.health = self.maxHealth
  self.mp = self.maxMp

func damage(amount:int, crit:bool) -> void:
  assert(amount >= 0)
  if status == Status.DEAD:
    return
  health = max(health - amount, 0)
  healthChanged.emit(-amount, crit)
  if health == 0:
    var oldStatus = status
    status = Status.DEAD
    statusChanged.emit(oldStatus, status)

func heal(amount:int) -> void:
  assert(amount > 0)
  if status == Status.DEAD:
    return
  health = min(health + amount, maxHealth)
  healthChanged.emit(amount, false)

func revive(health:int) -> void:
  assert(health > 0)
  if status != Status.DEAD:
    return
  health = min(health, maxHealth)
  status = Status.NORMAL
  self.health = health
  statusChanged.emit(Status.DEAD, Status.NORMAL)
  healthChanged.emit(health)

func mpConsume(amount:int) -> void:
  assert(amount > 0)
  mp = max(mp - amount, 0)
  mpChanged.emit(-amount)

func mpRestore(amount:int) -> void:
  assert(amount > 0)
  mp = min(mp + amount, maxMp)
  mpChanged.emit(amount)

func isPlayerControlled() -> bool:
  return controller == FighterController.PLAYER

func getAIDecision() -> BattleDecision:
  if !canMakeDecision():
    return null
  return null

func canMakeDecision() -> bool:
  return status != Status.DEAD

func canPlayerMakeDecision() -> bool:
  return isPlayerControlled() && canMakeDecision()
