package calc

import "math"

// Эффективность двигателя -
// равна мощности Двигателей, умноженной на технологический уровень блока Двигателей
func DriveEffective(drive, driveTech float64) float64 {
	return drive * driveTech
}

// Масса перевозимого груза -
// общее количество единиц груза, деленное на технологический уровень Грузоперевозок
func CarryingMass(load, cargoTech float64) float64 {
	if load <= 0 {
		return 0
	}
	return load / cargoTech
}

// Грузоподъёмность одного корабля
func CargoCapacity(cargo, cargoTech float64) float64 {
	return cargoTech * (cargo + (cargo*cargo)/20)
}

// Корабли перемещаются за один ход на количество световых лет, равное
// эффективности двигателя, умноженной на 20 и деленной на "Полную массу" корабля
func Speed(driveEffective, fullMass float64) float64 {
	if fullMass <= 0 {
		return 0
	}
	return driveEffective * 20 / fullMass
}

// Полная масса -
// массу корабля самого по себе плюс масса перевозимого груза
func FullMass(emptyMass, carryingMass float64) float64 {
	return emptyMass + carryingMass
}

func EmptyMass(drive, weapons float64, armament uint, shields, cargo float64) (float64, bool) {
	wm, ok := WeaponsBlockMass(weapons, armament)
	if !ok {
		return 0, false
	}
	return drive + shields + cargo + wm, true
}

func WeaponsBlockMass(weapons float64, armament uint) (float64, bool) {
	if (armament == 0 && weapons != 0) || (armament != 0 && weapons == 0) {
		return 0, false
	}
	return float64(armament+1) * (weapons / 2), true
}

// Стоимость модернизации одного блока корабля -
// доля недостающего технологического уровня (1 - currentBlockTech/targetBlockTech),
// умноженная на массу блока и нормирующий коэффициент 10.
// Возвращает 0, если масса блока равна нулю или целевой уровень не выше текущего.
func BlockUpgradeCost(blockMass, currentBlockTech, targetBlockTech float64) float64 {
	if blockMass == 0 || targetBlockTech <= currentBlockTech {
		return 0
	}
	return (1 - currentBlockTech/targetBlockTech) * 10 * blockMass
}

func DestructionProbability(
	attackingWeapons,
	attackingWeaponsTech,
	defendingShields,
	defendingShiledsTech,
	defendingFullMass float64,
) float64 {
	return DestructionProbabilityEffective(
		EffectiveAttack(attackingWeapons, attackingWeaponsTech),
		EffectiveDefence(defendingShields, defendingShiledsTech, defendingFullMass),
	)
}

func DestructionProbabilityEffective(effectiveAttack, effectiveDefence float64) float64 {
	return (math.Log10(effectiveAttack/effectiveDefence)/math.Log10(4) + 1) / 2
}

func EffectiveAttack(weapons, weaponsTech float64) float64 {
	return weapons * weaponsTech
}

func EffectiveDefence(
	defendingShields,
	defendingShiledsTech,
	defendingFullMass float64,
) float64 {
	if defendingFullMass <= 0 {
		return 0
	}
	return defendingShields * defendingShiledsTech / math.Pow(defendingFullMass, 1./3.) * math.Pow(30., 1./3.)
}
