package be.iminds.ilabt.jfed.experimenter_gui.ui;

import javafx.beans.property.BooleanProperty;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.scene.Group;
import javafx.scene.paint.Color;
import javafx.scene.shape.Rectangle;
import javafx.scene.text.Text;

/**
 * User: twalcari
 * Date: 9/16/2015
 * Time: 14:38
 */
public class AvailabilityMeter extends Group {

    private static final int HEIGHT = 20;

    protected final Rectangle outerAvailablityRect = new Rectangle(10, HEIGHT, Color.LIGHTGRAY);
    protected final Rectangle innerAvailablityRect = new Rectangle(10, HEIGHT, Color.LIGHTGRAY);
    protected final Text undeterminedText = new Text("?");

    private final IntegerProperty available = new SimpleIntegerProperty();
    private final IntegerProperty total = new SimpleIntegerProperty();

    private final BooleanProperty useVmCalculationMethod = new SimpleBooleanProperty(false);
    private final BooleanProperty undetermined = new SimpleBooleanProperty(false);


    public AvailabilityMeter() {
        undeterminedText.setX(2);
        undeterminedText.setY(15);

        undeterminedText.visibleProperty().bind(undetermined);
        getChildren().addAll(outerAvailablityRect, innerAvailablityRect, undeterminedText);


        available.addListener(observable -> update());
        total.addListener(observable -> update());
        useVmCalculationMethod.addListener(observable -> update());
    }

    /**
     *
     * @return double between 0 and 1
     */
    private double calculateHeight(){
        if(available.get() == 0)
            return 0;

        if(useVmCalculationMethod.get()){
            double value =
                    10.0 - (-0.6 / 0.005) * (1 - Math.exp(-0.005 * available.get()));  //function which goes to 130 in infinity
            value /= 130.0; //normalize to 1

            return value;
        }   else{
             return Math.min(available.get(), 100) / 100.0;
        }

    }

    private void update(){
        double newHeight = calculateHeight();

        innerAvailablityRect.setY(HEIGHT * (1.0 - newHeight));
        innerAvailablityRect.setHeight(HEIGHT * newHeight);

        if (newHeight > 0.75)
            innerAvailablityRect.setFill(Color.GREEN);
        else if (newHeight > 0.50)
            innerAvailablityRect.setFill(Color.YELLOWGREEN);
        else if (newHeight > 0.25)
            innerAvailablityRect.setFill(Color.ORANGE);
        else
            innerAvailablityRect.setFill(Color.RED);
    }

    public int getAvailable() {
        return available.get();
    }

    public IntegerProperty availableProperty() {
        return available;
    }

    public void setAvailable(int available) {
        this.available.set(available);
    }

    public int getTotal() {
        return total.get();
    }

    public IntegerProperty totalProperty() {
        return total;
    }

    public void setTotal(int total) {
        this.total.set(total);
    }

    public boolean getUseVmCalculationMethod() {
        return useVmCalculationMethod.get();
    }

    public BooleanProperty useVmCalculationMethodProperty() {
        return useVmCalculationMethod;
    }

    public void setUseVmCalculationMethod(boolean useVmCalculationMethod) {
        this.useVmCalculationMethod.set(useVmCalculationMethod);
    }

    public boolean getUndetermined() {
        return undetermined.get();
    }

    public BooleanProperty undeterminedProperty() {
        return undetermined;
    }

    public void setUndetermined(boolean undetermined) {
        this.undetermined.set(undetermined);
    }
}
