export function experienceForLevel(level) {
  return 100 * (level - 1) ** 2
}

export function catchUpExperienceReward(baseReward, currentExperience, targetExperience) {
  const gap = Math.max(0, targetExperience - currentExperience)
  if (gap <= 0) return baseReward
  const doubledBase = Math.min(baseReward, Math.ceil(gap / 2))
  return doubledBase * 2 + (baseReward - doubledBase)
}

export function scaledPvpBossExperience(
  startingExperience,
  startingLevel,
  bossesCleared,
  maxLevel,
  targetLevel = startingLevel,
  levelExperience = experienceForLevel,
) {
  let experience = startingExperience
  let level = startingLevel
  const maxExperience = levelExperience(maxLevel)
  for (let bossIndex = 0; bossIndex < bossesCleared && experience < maxExperience; bossIndex += 1) {
    const currentLevelFloor = levelExperience(level)
    const nextLevelExperience = level >= maxLevel
      ? maxExperience
      : levelExperience(level + 1)
    const levelBand = Math.max(1, nextLevelExperience - currentLevelFloor)
    const rewardRate = targetLevel > level ? 0.5 : 0.25
    experience = Math.min(maxExperience, experience + Math.round(levelBand * rewardRate))
    while (level < maxLevel && levelExperience(level + 1) <= experience) {
      level += 1
    }
  }
  return { experience, level }
}

export function scaledPvpFightExperience(
  startingExperience,
  startingLevel,
  fightsCleared,
  maxLevel,
  targetLevel = startingLevel,
  levelExperience = experienceForLevel,
) {
  let experience = startingExperience
  let level = startingLevel
  const maxExperience = levelExperience(maxLevel)
  for (let fightIndex = 0; fightIndex < fightsCleared && experience < maxExperience; fightIndex += 1) {
    const currentLevelFloor = levelExperience(level)
    const nextLevelExperience = level >= maxLevel
      ? maxExperience
      : levelExperience(level + 1)
    const levelBand = Math.max(1, nextLevelExperience - currentLevelFloor)
    const rewardRate = targetLevel > level ? 1 / 6 : 1 / 12
    experience = Math.min(maxExperience, experience + Math.round(levelBand * rewardRate))
    while (level < maxLevel && levelExperience(level + 1) <= experience) {
      level += 1
    }
  }
  return { experience, level }
}

export function scaledCurrentLevelExperience(
  startingExperience,
  startingLevel,
  maxLevel,
  rate,
  levelExperience = experienceForLevel,
) {
  let experience = startingExperience
  let level = startingLevel
  const maxExperience = levelExperience(maxLevel)
  const currentLevelFloor = levelExperience(level)
  const nextLevelExperience = level >= maxLevel
    ? maxExperience
    : levelExperience(level + 1)
  const levelBand = Math.max(1, nextLevelExperience - currentLevelFloor)
  experience = Math.min(maxExperience, experience + Math.round(levelBand * rate))
  while (level < maxLevel && levelExperience(level + 1) <= experience) {
    level += 1
  }
  return { experience, level }
}

export function coinDropQuantity() {
  const roll = Math.random()
  if (roll < 0.15) return 3
  if (roll < 0.5) return 2
  return 1
}

export function roguelikeCoinItemLevel(stage) {
  return Math.min(25, 5 + Math.max(0, Math.floor(stage / 5)) * 5)
}
