package com.livingworld.modules.soil;

/**
 * Per-region soil state tracked by {@link SoilModule}.
 *
 * <p>Five interacting values describe the physical and chemical condition of the
 * land in a region. All values are clamped to [0, 100].
 *
 * <ul>
 *   <li><b>fertility</b> – capacity to support plant growth (higher is better)
 *   <li><b>moisture</b>  – water content in soil (too low or too high is harmful)
 *   <li><b>contamination</b> – chemical or biological pollution absorbed by soil
 *   <li><b>compaction</b> – density of soil; high compaction resists root growth
 *   <li><b>erosion</b>   – structural loss of topsoil (higher is worse)
 * </ul>
 */
public final class SoilRegionData {

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

    private double fertility;
    private double moisture;
    private double contamination;
    private double compaction;
    private double erosion;

    public SoilRegionData(
            double fertility,
            double moisture,
            double contamination,
            double compaction,
            double erosion) {
        this.fertility     = clamp(fertility);
        this.moisture      = clamp(moisture);
        this.contamination = clamp(contamination);
        this.compaction    = clamp(compaction);
        this.erosion       = clamp(erosion);
    }

    /** Returns a healthy default soil profile. */
    public static SoilRegionData defaults() {
        return new SoilRegionData(60.0, 50.0, 0.0, 10.0, 0.0);
    }

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

    public double getFertility()     { return fertility; }
    public double getMoisture()      { return moisture; }
    public double getContamination() { return contamination; }
    public double getCompaction()    { return compaction; }
    public double getErosion()       { return erosion; }

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

    /**
     * Degrades soil by the given amount.
     *
     * <p>Reduces fertility and increases contamination proportionally.
     *
     * @param amount positive degradation magnitude
     */
    public void degrade(double amount) {
        if (amount < 0) throw new IllegalArgumentException("amount must be >= 0");
        fertility     = clamp(fertility     - amount);
        contamination = clamp(contamination + amount * 0.5);
        erosion       = clamp(erosion       + amount * 0.3);
    }

    /**
     * Applies ecological recovery by the given amount.
     *
     * <p>Increases fertility and reduces contamination and erosion.
     *
     * @param amount positive recovery magnitude
     */
    public void recover(double amount) {
        if (amount < 0) throw new IllegalArgumentException("amount must be >= 0");
        fertility     = clamp(fertility     + amount);
        contamination = clamp(contamination - amount * 0.4);
        erosion       = clamp(erosion       - amount * 0.3);
    }

    public void setFertility(double v)     { fertility     = clamp(v); }
    public void setMoisture(double v)      { moisture      = clamp(v); }
    public void setContamination(double v) { contamination = clamp(v); }
    public void setCompaction(double v)    { compaction    = clamp(v); }
    public void setErosion(double v)       { erosion       = clamp(v); }

    /** Clamps all fields to [0, 100]. */
    public void normalize() {
        fertility     = clamp(fertility);
        moisture      = clamp(moisture);
        contamination = clamp(contamination);
        compaction    = clamp(compaction);
        erosion       = clamp(erosion);
    }

    /** Returns an independent copy. */
    public SoilRegionData copy() {
        return new SoilRegionData(fertility, moisture, contamination, compaction, erosion);
    }

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

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

    @Override
    public String toString() {
        return "SoilRegionData{"
                + "fertility=" + fertility
                + ", moisture=" + moisture
                + ", contamination=" + contamination
                + ", compaction=" + compaction
                + ", erosion=" + erosion + "}";
    }
}
