package com.livingworld.modules.resources;

/**
 * Per-region resource depletion state tracked by {@link ResourceDepletionModule}.
 *
 * <p>Three independent depletion layers model how intensively each type of
 * resource harvesting has affected the region. All values are clamped to [0, 100],
 * where 0 means untouched and 100 means completely exhausted.
 *
 * <ul>
 *   <li><b>miningDepletion</b> – how heavily the region's mineral resources have
 *       been extracted (very slow natural recovery)
 *   <li><b>loggingDepletion</b> – how heavily trees have been harvested (recovery
 *       is linked to vegetation succession)
 *   <li><b>farmingDepletion</b> – how heavily the land has been cultivated without
 *       rest (recovery driven by soil quality)
 * </ul>
 *
 * <p>Depletion events are recorded via {@link #recordMining}, {@link #recordLogging},
 * and {@link #recordFarming}, which are intended to be called from platform-layer
 * event handlers when players interact with the world.
 */
public final class ResourceRegionData {

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

    private double miningDepletion;
    private double loggingDepletion;
    private double farmingDepletion;

    public ResourceRegionData(double miningDepletion, double loggingDepletion, double farmingDepletion) {
        this.miningDepletion  = clamp(miningDepletion);
        this.loggingDepletion = clamp(loggingDepletion);
        this.farmingDepletion = clamp(farmingDepletion);
    }

    /** Returns a pristine, unextracted region. */
    public static ResourceRegionData defaults() {
        return new ResourceRegionData(0.0, 0.0, 0.0);
    }

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

    public double getMiningDepletion()  { return miningDepletion; }
    public double getLoggingDepletion() { return loggingDepletion; }
    public double getFarmingDepletion() { return farmingDepletion; }

    /** Weighted total depletion score, matching the metric written to {@link com.livingworld.regions.RegionMetrics}. */
    public double totalDepletion() {
        return clamp(miningDepletion * 0.50 + loggingDepletion * 0.30 + farmingDepletion * 0.20);
    }

    // ------------------------------------------------------------------
    // Depletion events (called by platform event handlers)
    // ------------------------------------------------------------------

    /**
     * Records a mining event of the given intensity.
     *
     * @param intensity depletion to add (0–100)
     */
    public void recordMining(double intensity) {
        if (intensity < 0) throw new IllegalArgumentException("intensity must be >= 0");
        miningDepletion = clamp(miningDepletion + intensity);
    }

    /**
     * Records a logging event of the given intensity.
     *
     * @param intensity depletion to add (0–100)
     */
    public void recordLogging(double intensity) {
        if (intensity < 0) throw new IllegalArgumentException("intensity must be >= 0");
        loggingDepletion = clamp(loggingDepletion + intensity);
    }

    /**
     * Records a farming event of the given intensity.
     *
     * @param intensity depletion to add (0–100)
     */
    public void recordFarming(double intensity) {
        if (intensity < 0) throw new IllegalArgumentException("intensity must be >= 0");
        farmingDepletion = clamp(farmingDepletion + intensity);
    }

    // ------------------------------------------------------------------
    // Internal setters (used by the module's regeneration logic)
    // ------------------------------------------------------------------

    public void setMiningDepletion(double v)  { miningDepletion  = clamp(v); }
    public void setLoggingDepletion(double v) { loggingDepletion = clamp(v); }
    public void setFarmingDepletion(double v) { farmingDepletion = clamp(v); }

    /** Clamps all fields to [0, 100]. */
    public void normalize() {
        miningDepletion  = clamp(miningDepletion);
        loggingDepletion = clamp(loggingDepletion);
        farmingDepletion = clamp(farmingDepletion);
    }

    /** Returns an independent copy. */
    public ResourceRegionData copy() {
        return new ResourceRegionData(miningDepletion, loggingDepletion, farmingDepletion);
    }

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

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

    @Override
    public String toString() {
        return "ResourceRegionData{"
                + "mining=" + miningDepletion
                + ", logging=" + loggingDepletion
                + ", farming=" + farmingDepletion + "}";
    }
}
