import type { Spell } from '../game'

export function cooldownNow() {
  return Date.now()
}

export function cooldownRemaining(
  cooldowns: Record<string, number>,
  spellId: string,
  now = cooldownNow(),
) {
  return Math.max(0, ((cooldowns[spellId] ?? 0) - now) / 1000)
}

export function hasActiveCooldowns(
  cooldowns: Record<string, number>,
  now = cooldownNow(),
) {
  return Object.values(cooldowns).some((readyAtMs) => readyAtMs > now)
}

export function pruneExpiredCooldowns(
  cooldowns: Record<string, number>,
  now = cooldownNow(),
) {
  let changed = false
  const nextCooldowns: Record<string, number> = {}
  for (const id in cooldowns) {
    if (cooldowns[id] <= now) {
      changed = true
      continue
    }
    nextCooldowns[id] = cooldowns[id]
  }
  return changed ? nextCooldowns : cooldowns
}

export function reduceCooldown(
  cooldowns: Record<string, number>,
  spellId: string,
  seconds: number,
  now = cooldownNow(),
) {
  const readyAtMs = cooldowns[spellId]
  if (!readyAtMs || readyAtMs <= now) return cooldowns
  const nextReadyAtMs = readyAtMs - seconds * 1000
  const nextCooldowns = { ...cooldowns }
  if (nextReadyAtMs <= now) delete nextCooldowns[spellId]
  else nextCooldowns[spellId] = nextReadyAtMs
  return nextCooldowns
}

export function canCastSpell(
  spell: Spell,
  resource: number,
  cooldowns: Record<string, number>,
  resourceCost: number,
  now = cooldownNow(),
) {
  return resource >= resourceCost && cooldownRemaining(cooldowns, spell.id, now) <= 0
}

export function putSpellOnCooldown(
  cooldowns: Record<string, number>,
  spell: Spell,
  cooldownMultiplier = 1,
  now = cooldownNow(),
) {
  const cooldownMs = spell.cooldown * cooldownMultiplier * 1000
  if (cooldownMs <= 0) {
    const nextCooldowns = { ...cooldowns }
    delete nextCooldowns[spell.id]
    return nextCooldowns
  }
  return {
    ...cooldowns,
    [spell.id]: now + cooldownMs,
  }
}
