package com.livingworld.modules.pollution;

/**
 * Per-region pollution state tracked by {@link PollutionModule}.
 *
 * <p>Stores three independent pollution layers (air, ground, water) and a decay
 * resistance score. All values are clamped to [0, 100].
 *
 * <p>Decay resistance slows natural recovery. A brand-new region has zero
 * pollution and low decay resistance, meaning pollution introduced there will
 * dissipate quickly.
 */
public final class PollutionRegionData {

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

    private double airPollution;
    private double groundPollution;
    private double waterPollution;
    private double decayResistance;

    public PollutionRegionData(
            double airPollution,
            double groundPollution,
            double waterPollution,
            double decayResistance) {
        this.airPollution = clamp(airPollution);
        this.groundPollution = clamp(groundPollution);
        this.waterPollution = clamp(waterPollution);
        this.decayResistance = clamp(decayResistance);
    }

    /** Returns a clean region with low decay resistance. */
    public static PollutionRegionData defaults() {
        return new PollutionRegionData(0.0, 0.0, 0.0, 20.0);
    }

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

    public double getAirPollution()    { return airPollution; }
    public double getGroundPollution() { return groundPollution; }
    public double getWaterPollution()  { return waterPollution; }
    public double getDecayResistance() { return decayResistance; }

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

    /** Adds pollution to each layer; values are clamped after addition. */
    public void addPollution(double air, double ground, double water) {
        airPollution    = clamp(airPollution    + air);
        groundPollution = clamp(groundPollution + ground);
        waterPollution  = clamp(waterPollution  + water);
    }

    /**
     * Applies a single natural-decay tick.
     *
     * <p>{@code baseRate} is the fraction removed per tick before resistance is
     * applied (e.g. 0.02 = 2 %). Decay resistance reduces the effective rate:
     * effective = baseRate * (1 - decayResistance / 200).
     *
     * @param baseRate fraction to decay per tick (0–1)
     */
    public void decay(double baseRate) {
        double resistanceFactor = 1.0 - (decayResistance / 200.0);
        double effectiveRate = Math.max(0.0, baseRate * resistanceFactor);
        airPollution    = clamp(airPollution    * (1.0 - effectiveRate * 2.0));
        groundPollution = clamp(groundPollution * (1.0 - effectiveRate * 0.5));
        waterPollution  = clamp(waterPollution  * (1.0 - effectiveRate * 0.3));
    }

    /** Clamps all fields to [0, 100]. */
    public void normalize() {
        airPollution    = clamp(airPollution);
        groundPollution = clamp(groundPollution);
        waterPollution  = clamp(waterPollution);
        decayResistance = clamp(decayResistance);
    }

    /** Returns an independent copy. */
    public PollutionRegionData copy() {
        return new PollutionRegionData(airPollution, groundPollution, waterPollution, decayResistance);
    }

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

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

    @Override
    public String toString() {
        return "PollutionRegionData{"
                + "air=" + airPollution
                + ", ground=" + groundPollution
                + ", water=" + waterPollution
                + ", decayResistance=" + decayResistance + "}";
    }
}
