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

namespace LittleSim.Sim;

/// <summary>
/// Признаки (фенотип) животного, вычисленные из генома формулами генов (см. <c>genes.json</c>):
/// готовые значения, которые читают системы, не касаясь генов напрямую. Зеркало
/// <see cref="PlantPhenotype"/>. Имена полей соответствуют именам признаков в эффектах генов.
/// </summary>
public struct AnimalPhenotype
{
    /// <summary>Размер тела в клетках (масштаб спрайта; позже — HP/расход энергии).</summary>
    public float BodySize;

    /// <summary>Скорость обмена веществ — множитель расхода нужд.</summary>
    public float Metabolism;

    /// <summary>Скорость передвижения (множитель).</summary>
    public float MoveSpeed;

    /// <summary>Объём крови (множитель) — масштаб скорости кровопотери.</summary>
    public float BloodVolume;

    /// <summary>Дальность зрения (множитель радиуса поиска).</summary>
    public float Vision;

    /// <summary>Размер мозга (0..1) — основа интеллекта.</summary>
    public float BrainSize;

    /// <summary>Теплоизоляция мехом (0..1).</summary>
    public float Insulation;

    /// <summary>Оттенок меха (0..1) — сдвиг тинта спрайта.</summary>
    public float FurHue;

    /// <summary>Продолжительность жизни (игровых дней).</summary>
    public float Lifespan;

    /// <summary>Собирает фенотип из карты признаков, посчитанной <see cref="Phenotype.Compute"/>.</summary>
    public static AnimalPhenotype FromTraits(IReadOnlyDictionary<string, float> traits)
    {
        float T(string name) => traits.GetValueOrDefault(name);
        return new AnimalPhenotype
        {
            BodySize = T("bodySize"),
            Metabolism = T("metabolism"),
            MoveSpeed = T("moveSpeed"),
            BloodVolume = T("bloodVolume"),
            Vision = T("vision"),
            BrainSize = T("brainSize"),
            Insulation = T("insulation"),
            FurHue = T("furHue"),
            Lifespan = T("lifespan"),
        };
    }
}

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

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

    /// <summary>Индекс вида в <see cref="Content.AnimalSet"/>.</summary>
    public int Species;

    /// <summary>Номер поколения: max(родителей) + 1; у основателей 0.</summary>
    public int Generation;
}
