package main

import "math/rand"

// WayfarerEncounterType — вид случайной встречи во время перелёта.
type WayfarerEncounterType int

const (
	EncounterNone WayfarerEncounterType = iota
	EncounterPirate
	EncounterPoliceScan
	EncounterDistress
	EncounterDerelict
)

// wayfarerBaseEncounterChance — базовая вероятность хоть какой-то
// встречи за один прыжок при "нейтральном" (danger factor = 1)
// уровне опасности системы назначения.
const wayfarerBaseEncounterChance = 0.18

// RollEncounter решает, произойдёт ли что-то во время перелёта в
// систему dest, и если да — что именно.
func RollEncounter(dest WayfarerSystem, rnd *rand.Rand) WayfarerEncounterType {
	chance := wayfarerBaseEncounterChance * dest.DangerFactor()
	if chance > 0.9 {
		chance = 0.9
	}
	if rnd.Float64() > chance {
		return EncounterNone
	}
	roll := rnd.Float64()
	switch {
	case roll < 0.45:
		return EncounterPirate
	case roll < 0.65:
		return EncounterPoliceScan
	case roll < 0.85:
		return EncounterDistress
	default:
		return EncounterDerelict
	}
}

// GeneratePirateStats создаёт статы вражеского корабля,
// отмасштабированные под опасность системы dest — в более опасных
// (например, анархических) системах пираты в среднем крепче и злее.
func GeneratePirateStats(dest WayfarerSystem, rnd *rand.Rand) (hull, laser, shield int) {
	baseHull := 15 + rnd.Intn(20)
	baseLaser := 4 + rnd.Intn(6)
	baseShield := rnd.Intn(20) // некоторые пираты вообще без щита — это нормально, не форсируем минимум
	hull = int(float64(baseHull) * dest.DangerFactor())
	laser = int(float64(baseLaser) * dest.DangerFactor())
	shield = int(float64(baseShield) * dest.DangerFactor())
	if hull < 5 {
		hull = 5
	}
	if laser < 1 {
		laser = 1
	}
	if shield < 0 {
		shield = 0
	}
	return hull, laser, shield
}

// HasIllegalCargo проверяет, везёт ли корабль хоть что-то из
// незаконных товаров (WayfarerCommodities[i].Illegal).
func (s *WayfarerShip) HasIllegalCargo() bool {
	for i, c := range WayfarerCommodities {
		if c.Illegal && s.Cargo[i] > 0 {
			return true
		}
	}
	return false
}

// ConfiscateIllegalCargo изымает весь незаконный груз и возвращает
// его условную стоимость (для отображения игроку, что он потерял).
func (s *WayfarerShip) ConfiscateIllegalCargo() float64 {
	lost := 0.0
	for i, c := range WayfarerCommodities {
		if c.Illegal && s.Cargo[i] > 0 {
			lost += float64(s.Cargo[i]) * c.BasePrice
			s.Cargo[i] = 0
		}
	}
	return lost
}

// wayfarerDerelictMin/Max — диапазон случайной находки на обломках.
const (
	wayfarerDerelictMin = 50.0
	wayfarerDerelictMax = 250.0
)

// DerelictFind начисляет игроку случайную находку с обломков
// корабля и возвращает её размер.
func (s *WayfarerShip) DerelictFind(rnd *rand.Rand) float64 {
	found := wayfarerDerelictMin + rnd.Float64()*(wayfarerDerelictMax-wayfarerDerelictMin)
	s.Credits += found
	return found
}

// wayfarerQuestOfferChance — с такой вероятностью прибытие в
// систему (если сейчас нет активного задания и остались
// невыполненные/непровальные квесты) заканчивается предложением
// одного из них — вместо свободного выбора квеста из списка когда
// угодно, как раньше.
const wayfarerQuestOfferChance = 0.25

// RollQuestOffer решает, предлагается ли игроку квест по прибытии в
// систему. Возвращает (ключ квеста, true), если да.
func RollQuestOffer(ship *WayfarerShip, rnd *rand.Rand) (string, bool) {
	if ship.ActiveQuest != nil {
		return "", false
	}
	var candidates []string
	for _, q := range WayfarerQuestDefs {
		if !ship.CompletedQuests[q.Key] && !ship.FailedQuests[q.Key] {
			candidates = append(candidates, q.Key)
		}
	}
	if len(candidates) == 0 {
		return "", false
	}
	if rnd.Float64() > wayfarerQuestOfferChance {
		return "", false
	}
	return candidates[rnd.Intn(len(candidates))], true
}

// wayfarerDistressTrapChance — с такой вероятностью сигнал бедствия
// на самом деле окажется засадой (тогда вызывающий код должен
// начать бой) вместо честной просьбы о помощи.
const wayfarerDistressTrapChance = 0.25

const (
	wayfarerDistressRewardMin = 100.0
	wayfarerDistressRewardMax = 400.0
)

// HelpDistressed разрешает решение "откликнуться на сигнал
// бедствия": либо это оказывается ловушка (wasTrap == true — бой
// должен запустить вызывающий код отдельно, начисление тут не
// происходит), либо честная награда за помощь.
func (s *WayfarerShip) HelpDistressed(rnd *rand.Rand) (reward float64, wasTrap bool) {
	if rnd.Float64() < wayfarerDistressTrapChance {
		return 0, true
	}
	reward = wayfarerDistressRewardMin + rnd.Float64()*(wayfarerDistressRewardMax-wayfarerDistressRewardMin)
	s.Credits += reward
	return reward, false
}
