package com.livingworld.modules.vegetation;

/**
 * Per-region vegetation state tracked by {@link VegetationModule}.
 *
 * <p>Five values capture the biomass distribution and health of plant cover in a
 * region. All values are clamped to [0, 100].
 *
 * <ul>
 *   <li><b>grassPressure</b>  – density and health of grass-layer plants
 *   <li><b>flowerPressure</b> – density and health of flowering plants
 *   <li><b>shrubPressure</b>  – density and health of shrubs / undergrowth
 *   <li><b>treePressure</b>   – density and health of tree canopy
 *   <li><b>deadVegetation</b> – accumulated dead organic material (higher = more decay burden)
 * </ul>
 *
 * <p>Vegetation succession naturally flows from grass → flowers → shrubs → trees
 * when conditions allow. Damage reverses this sequence and raises deadVegetation.
 */
public final class VegetationRegionData {

    private static final double MIN = 0.0;
    private static final double MAX = 100.0;

    private double grassPressure;
    private double flowerPressure;
    private double shrubPressure;
    private double treePressure;
    private double deadVegetation;

    public VegetationRegionData(
            double grassPressure,
            double flowerPressure,
            double shrubPressure,
            double treePressure,
            double deadVegetation) {
        this.grassPressure  = clamp(grassPressure);
        this.flowerPressure = clamp(flowerPressure);
        this.shrubPressure  = clamp(shrubPressure);
        this.treePressure   = clamp(treePressure);
        this.deadVegetation = clamp(deadVegetation);
    }

    /** Returns a default mixed-vegetation profile. */
    public static VegetationRegionData defaults() {
        return new VegetationRegionData(50.0, 30.0, 30.0, 40.0, 5.0);
    }

    // ------------------------------------------------------------------
    // Getters
    // ------------------------------------------------------------------

    public double getGrassPressure()  { return grassPressure; }
    public double getFlowerPressure() { return flowerPressure; }
    public double getShrubPressure()  { return shrubPressure; }
    public double getTreePressure()   { return treePressure; }
    public double getDeadVegetation() { return deadVegetation; }

    // ------------------------------------------------------------------
    // Mutation
    // ------------------------------------------------------------------

    /**
     * Simulates the impact of logging or clear-cutting by the given amount.
     *
     * <p>Reduces tree and shrub pressure while increasing dead vegetation
     * proportionally.
     *
     * @param amount positive logging damage magnitude
     */
    public void reduceFromLogging(double amount) {
        if (amount < 0) throw new IllegalArgumentException("amount must be >= 0");
        treePressure   = clamp(treePressure   - amount);
        shrubPressure  = clamp(shrubPressure  - amount * 0.5);
        deadVegetation = clamp(deadVegetation + amount * 0.8);
    }

    /**
     * Applies ecological recovery across all vegetation layers by the given amount.
     *
     * <p>Increases all living pressures modestly and reduces dead vegetation.
     *
     * @param amount positive recovery magnitude
     */
    public void recover(double amount) {
        if (amount < 0) throw new IllegalArgumentException("amount must be >= 0");
        grassPressure  = clamp(grassPressure  + amount);
        flowerPressure = clamp(flowerPressure + amount * 0.7);
        shrubPressure  = clamp(shrubPressure  + amount * 0.5);
        treePressure   = clamp(treePressure   + amount * 0.3);
        deadVegetation = clamp(deadVegetation - amount * 0.6);
    }

    public void setGrassPressure(double v)  { grassPressure  = clamp(v); }
    public void setFlowerPressure(double v) { flowerPressure = clamp(v); }
    public void setShrubPressure(double v)  { shrubPressure  = clamp(v); }
    public void setTreePressure(double v)   { treePressure   = clamp(v); }
    public void setDeadVegetation(double v) { deadVegetation = clamp(v); }

    /** Clamps all fields to [0, 100]. */
    public void normalize() {
        grassPressure  = clamp(grassPressure);
        flowerPressure = clamp(flowerPressure);
        shrubPressure  = clamp(shrubPressure);
        treePressure   = clamp(treePressure);
        deadVegetation = clamp(deadVegetation);
    }

    /** Returns an independent copy. */
    public VegetationRegionData copy() {
        return new VegetationRegionData(
                grassPressure, flowerPressure, shrubPressure, treePressure, deadVegetation);
    }

    // ------------------------------------------------------------------

    private static double clamp(double v) {
        return Math.min(MAX, Math.max(MIN, v));
    }

    @Override
    public String toString() {
        return "VegetationRegionData{"
                + "grass=" + grassPressure
                + ", flower=" + flowerPressure
                + ", shrub=" + shrubPressure
                + ", tree=" + treePressure
                + ", dead=" + deadVegetation + "}";
    }
}
