package uebung05.logistics.storage;

import uebung05.logistics.quantities.FloatUnit;
import uebung05.logistics.quantities.NeedCollector;

/**
 * The FloatStorage class represents a floating-point storage for a specific FloatUnit object.
 * It includes methods for getting the unit, stored amount, and maximum capacity, as well as
 * methods for consuming, filling, and reporting needs.
 *
 * @author Nikolaus Köberlein
 * @version 1.0
 */
public class FloatStorage implements FloatUnit {

    private final FloatUnit unit;
    private float stored;
    private final float max;

    /**
     * Construct a FloatStorage object with a stored amount, FloatUnit object, and maximum capacity
     *
     * @param stored        The initial stored amount for the FloatStorage object
     * @param unit          The FloatUnit object for the FloatStorage object
     * @param max           The maximum capacity for the FloatStorage object
     *
     * @throws java.lang.IllegalArgumentException if unit is negative
     */
    public FloatStorage(float stored, FloatUnit unit, float max) {
        if (stored < 0 || max < 0) {
            throw new IllegalArgumentException("Units cannot be negative");
        }
        if (stored > max) {
            this.stored = max;
            this.unit = unit;
            this.max = max;
        } else {
            this.stored = stored;
            this.unit = unit;
            this.max = max;
        }
    }

    /**
     * Get the FloatUnit object for the FloatStorage object
     *
     * @return The FloatUnit object for the FloatStorage object
     */
    public FloatUnit getUnit() {
        return unit;
    }

    /**
     * Get the stored amount for the FloatStorage object
     *
     * @return The stored amount for the FloatStorage object
     */
    public float getStored() {
        return stored;
    }

    /**
     * Get the maximum capacity for the FloatStorage object
     *
     * @return The maximum capacity for the FloatStorage object
     */
    public float getMax() {
        return max;
    }

    /**
     * Consume a specific amount from the FloatStorage object
     *
     * @param amount The amount to consume from the FloatStorage object
     * @return The amount consumed from the FloatStorage object
     *
     * @throws java.lang.IllegalArgumentException if consume is negative
     */
    public float consume(float amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Consume cannot be negative");
        }
        if (stored < amount) {
            float newStored = stored;
            stored = 0;
            return newStored;
        }
        stored -= amount;
        return amount;
    }

    /**
     * Fill the FloatStorage object with a specific amount
     *
     * @param amount The amount to fill the FloatStorage object with
     *
     * @throws java.lang.IllegalArgumentException if consume is negative
     */
    public void fill(float amount) {
        if (amount < 0) {
            throw new IllegalArgumentException("Consume cannot be negative");
        }
        stored += amount;
        if (max < stored) {
            fillUp();
        }
    }

    /**
     * Fill the FloatStorage object to its maximum capacity
     */
    public void fillUp() {
        stored = max;
    }

    /**
     * Report the needs of the FloatStorage object to a NeedCollector object
     *
     * @param collector The NeedCollector object to which to report the needs
     */
    public void reportNeed (NeedCollector collector) {
        collector.add(max-stored, unit);
    }

    /**
     * Get a string representation of the FloatStorage object
     *
     * @return A string representation of the FloatStorage object
     */
    @Override
    public String toString() {
        return "storage with " + stored + " of " + max + " " + unit;
    }
}