package h05;

public abstract class Plane implements Flying {

    private static final double CONSUMPTION_PER_KM_KG = 1.1494e-4;

    private final String aircraftRegistration;

    private final int baseWeight;

    private final FuelType fuelType;

    private final double fuelCapacity;

    private double currentFuelLevel;

    public Plane(String aircraftRegistration, int baseWeight, FuelType fuelType, double fuelCapacity) {
        this.aircraftRegistration = aircraftRegistration;
        this.baseWeight = baseWeight;
        this.fuelType = fuelType;
        this.fuelCapacity = fuelCapacity;
        this.currentFuelLevel = 0;
    }

    @Override
    public String getIdentifier() {
        return aircraftRegistration;
    }

    public double getCurrentFuelLevel() {
        return currentFuelLevel;
    }

    public double getFuelCapacity() {
        return fuelCapacity;
    }

    public FuelType getFuelType() {
        return fuelType;
    }

    public int getBaseWeight() {
        return baseWeight;
    }

    public void refuel(double amount) {
        if (currentFuelLevel + amount > fuelCapacity) {
            System.out.printf("The Tank of Plane %s has overflowed!\n", aircraftRegistration);
            return;
        }

        currentFuelLevel += amount;
    }

    protected abstract double mass();

    protected double getFuelConsumptionPerKilometer() {
        return CONSUMPTION_PER_KM_KG * fuelType.getConsumptionMultiplicator() * mass();
    }

    public void fly(double distance) {
        var fuelNeeded = getFuelConsumptionPerKilometer() * distance;

        if (currentFuelLevel < fuelNeeded) {
            System.out.printf("Plane %s does not have enough fuel to fly %f km.", aircraftRegistration, distance / 100000);
            return;
        }

        currentFuelLevel -= fuelNeeded;
        System.out.printf("Plane %s flew %s km and has %s liters of fuel left.", aircraftRegistration, distance, currentFuelLevel);
    }

    public void takeOff() {
        Airspace.get().register(this);
    }

    public void land() {
        Airspace.get().deregister(this);
    }
}
