extends Node

const ABILITY_COUNT: int = 4

var _cds: Dictionary = {}
var _max_cds: Dictionary = {}
var _gcd: Dictionary = {}
var _aa: Dictionary = {}

func _ready() -> void:
  EventBus.entity_deregistered.connect(_on_dereg)
  EventBus.role_changed.connect(_on_role_changed)
  set_physics_process(true)

func register(entity: Node) -> void:
  _cds[entity] = PackedFloat32Array([0, 0, 0, 0])
  _max_cds[entity] = PackedFloat32Array([0, 0, 0, 0])
  _gcd[entity] = 0.0
  _aa[entity] = 0.0

func _on_dereg(entity: Node) -> void:
  _cds.erase(entity)
  _max_cds.erase(entity)
  _gcd.erase(entity)
  _aa.erase(entity)

func _on_role_changed(player: Node, _role: int) -> void:
  if player in _cds:
    var z: PackedFloat32Array = PackedFloat32Array([0, 0, 0, 0])
    _cds[player] = z
    _max_cds[player] = z.duplicate()
    _gcd[player] = 0.0
    _aa[player] = 0.0

func is_ready(entity: Node, index: int) -> bool:
  if not entity in _cds:
    return true
  if index < 0 or index >= ABILITY_COUNT:
    return false
  return _cds[entity][index] <= 0.0

func is_gcd_ready(entity: Node) -> bool:
  return _gcd.get(entity, 0.0) <= 0.0

func is_aa_ready(entity: Node) -> bool:
  return _aa.get(entity, 0.0) <= 0.0

func set_cooldown(entity: Node, index: int, cd: float, gcd: float = 0.0) -> void:
  if not entity in _cds:
    register(entity)
  _cds[entity][index] = cd
  _max_cds[entity][index] = cd
  if gcd > 0.0:
    _gcd[entity] = gcd

func set_aa(entity: Node, value: float) -> void:
  _aa[entity] = value

var _emit_accum: float = 0.0

func _physics_process(delta: float) -> void:
  for entity in _cds.keys():
    if not is_instance_valid(entity):
      continue
    var arr: PackedFloat32Array = _cds[entity]
    for i in range(arr.size()):
      if arr[i] > 0.0:
        arr[i] = max(0.0, arr[i] - delta)
    _cds[entity] = arr
    if _gcd.get(entity, 0.0) > 0.0:
      _gcd[entity] = max(0.0, _gcd[entity] - delta)
    if _aa.get(entity, 0.0) > 0.0:
      _aa[entity] = max(0.0, _aa[entity] - delta)
  _emit_accum += delta
  if _emit_accum < 0.10:
    return
  _emit_accum = 0.0
  for entity in _cds.keys():
    if is_instance_valid(entity) and entity.is_in_group("player") and entity.is_multiplayer_authority():
      EventBus.cooldown_tick.emit(entity, _cds[entity], _max_cds[entity], _gcd.get(entity, 0.0))
