using System.Collections.Generic;
using Friflo.Engine.ECS;
using MrGameEng.Genetics;

namespace LittleSim.Sim;

/// <summary>
/// Растительные признаки (фенотип), вычисленные из генома формулами генов (см. <c>genes.json</c>):
/// готовые значения, которые читают системы роста и жизненного цикла, не касаясь генов напрямую.
/// Имена полей соответствуют именам признаков в эффектах генов.
/// </summary>
public struct PlantPhenotype
{
    public float OptimalLight;
    public float LightTolerance;
    public float OptimalTemperature;
    public float TemperatureTolerance;
    public float ColdHardiness;
    public float HeatHardiness;
    public float OptimalFertility;
    public float FertilityTolerance;
    public float Vigor;
    public float Lifespan;
    public float DispersalRange;
    public float ReproduceInterval;
    public float SelfPollination;
    public float MutationRate;

    // --- Контент (G4): плодоношение, добыча, цвет ---
    public float FruitYield;
    public int FruitSeason;
    public float HarvestAmount;
    public float LeafHue;

    /// <summary>Морфа: рецессивный вариант (выраженное значение гена морфы ≈ 1) — другой тинт спрайта.</summary>
    public bool IsVariant;

    /// <summary>
    /// Четыре точки температурной трапеции роста (модель RimWorld): жёсткий минимум, нижний край плато,
    /// верхний край плато, жёсткий максимум. Плато — оптимум ± толерантность; жёсткие края отстоят от
    /// плато на морозо-/жаростойкость. Кормит <see cref="MrGameEng.AI.Suitability.Trapezoid"/>.
    /// </summary>
    public readonly (float Min, float OptimalLow, float OptimalHigh, float Max) TemperatureBand()
    {
        var low = OptimalTemperature - TemperatureTolerance;
        var high = OptimalTemperature + TemperatureTolerance;
        return (low - ColdHardiness, low, high, high + HeatHardiness);
    }

    /// <summary>Собирает фенотип из карты признаков, посчитанной <see cref="Phenotype.Compute"/>.</summary>
    public static PlantPhenotype FromTraits(IReadOnlyDictionary<string, float> traits)
    {
        float T(string name) => traits.GetValueOrDefault(name);
        return new PlantPhenotype
        {
            OptimalLight = T("optimalLight"),
            LightTolerance = T("lightTolerance"),
            OptimalTemperature = T("optimalTemperature"),
            TemperatureTolerance = T("temperatureTolerance"),
            ColdHardiness = T("coldHardiness"),
            HeatHardiness = T("heatHardiness"),
            OptimalFertility = T("optimalFertility"),
            FertilityTolerance = T("fertilityTolerance"),
            Vigor = T("vigor"),
            Lifespan = T("lifespan"),
            DispersalRange = T("dispersalRange"),
            ReproduceInterval = T("reproduceInterval"),
            SelfPollination = T("selfPollination"),
            MutationRate = T("mutationRate"),
            FruitYield = T("fruitYield"),
            FruitSeason = (int)MathF.Round(Math.Clamp(T("fruitSeason"), 0f, 3f)),
            HarvestAmount = T("harvestAmount"),
            LeafHue = T("leafHue"),
            IsVariant = T("variant") >= 0.5f,
        };
    }
}

/// <summary>
/// Компонент-организм растения: его управляемый <see cref="Genome"/> (для размножения, сейва и
/// пересчёта) и выраженный фенотип <see cref="Traits"/>, по которому работают системы. Заменяет
/// прежний фиксированный <c>PlantGenome</c> — теперь геном переменного состава и признаки из формул
/// генов (фаза G3). Геном — ссылочный объект, поэтому компонент несёт ссылку, а не копию.
/// </summary>
public struct PlantOrganism : IComponent
{
    /// <summary>Геном особи (аллели по генам); общий источник истины для признаков и размножения.</summary>
    public Genome Genome;

    /// <summary>Выраженные признаки — то, что читают системы роста/жизненного цикла.</summary>
    public PlantPhenotype Traits;
}

/// <summary>
/// Плодоношение растения: сколько зрелых плодов сейчас на нём. Копится у зрелого растения в его
/// сезон плодоношения (признак <see cref="PlantPhenotype.FruitSeason"/>) до потолка
/// <see cref="PlantPhenotype.FruitYield"/>, вне сезона опадает. Управляется <c>PlantFruitingSystem</c>.
/// </summary>
public struct Fruiting : IComponent
{
    /// <summary>Накоплено зрелых плодов (0..FruitYield).</summary>
    public float RipeFruit;
}

/// <summary>
/// Накопленный температурный стресс растения в игровых днях. Пока температура вне диапазона роста
/// (трапеция <see cref="PlantPhenotype.TemperatureBand"/> даёт ноль — слишком холодно или жарко),
/// стресс копится; внутри диапазона — рассасывается. Превышение порога убивает растение
/// (вымерзание/перегрев). Управляется <c>PlantLifecycleSystem</c>.
/// </summary>
public struct TemperatureStress : IComponent
{
    /// <summary>Накоплено дней дормантности вне диапазона роста; при превышении лимита — гибель.</summary>
    public float Days;
}
