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

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.experiment.ExperimentState;
import be.iminds.ilabt.jfed.experiment.util.NextExperimentExpiration;
import be.iminds.ilabt.jfed.experiment.util.NextExperimentExpirationBinding;
import be.iminds.ilabt.jfed.experimenter_gui.util.DateTimeUtils;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.binding.StringBinding;

import java.time.Instant;
import java.time.ZoneId;

/**
 * User: twalcari
 * Date: 1/30/2015
 * Time: 14:58
 */
public class ExperimentStatusProperty extends StringBinding {
    private final Experiment experiment;

    private final NextExperimentExpirationBinding nextExperimentExpirationBinding;
    private final Timeline expirationTickerTimeline;

    public ExperimentStatusProperty(Experiment experiment) {
        this.experiment = experiment;
        this.nextExperimentExpirationBinding = new NextExperimentExpirationBinding(experiment);
        bind(nextExperimentExpirationBinding);

        this.expirationTickerTimeline = new Timeline(
                new KeyFrame(javafx.util.Duration.ZERO, actionEvent -> invalidate()),
                new KeyFrame(new javafx.util.Duration(1000))
        );
        this.expirationTickerTimeline.setCycleCount(Animation.INDEFINITE);
        this.expirationTickerTimeline.play();
    }

    private String composeReservationStartMessage() {
        assert (experiment.getRequestedStartTime() != null && !experiment.getRequestedStartTime().isBefore(Instant.now()));


        java.time.Duration duration =
                java.time.Duration.between(Instant.now(), experiment.getRequestedStartTime()).withNanos(0);

        return String.format("The reservation for this experiment run will start on %s. It will start in %s.",
                DateTimeUtils.DATE_HOUR_MINUTES_FORMATTER.format(experiment.getRequestedStartTime().atZone(ZoneId.systemDefault())),
                DateTimeUtils.prettyPrintDuration(duration));

    }

    private String composeExpirationMessage() {
        NextExperimentExpiration nextExperimentExpiration = nextExperimentExpirationBinding.get();

        if (nextExperimentExpiration == null || nextExperimentExpiration.getFirstExpirationTime() == null)
            return "";

        StringBuilder message = new StringBuilder();

        if (nextExperimentExpiration.getFirstExpiringPart() == null) {
            message.append("This experiment run");
        } else {
            message.append("The resources on ").append(nextExperimentExpiration.getFirstExpiringPart().getName());
        }


        if (nextExperimentExpiration.getFirstExpirationTime().isAfter(Instant.now())) {
            java.time.Duration duration = java.time.Duration.between(Instant.now(),
                    nextExperimentExpiration.getFirstExpirationTime()).withNanos(0);


            message.append(" will expire in ")
                    .append(DateTimeUtils.prettyPrintDuration(duration))
                    .append(".");


            if (experiment.getExperimentState() == ExperimentState.EMPTY) {
                message.append(" (currently no resources active)");
            }
        } else {
            if (nextExperimentExpiration.getFirstExpiringPart() == null)
                message.append(" has EXPIRED!");
            else {
                message.append(" have EXPIRED!");
            }
        }

        return message.toString();
    }

    @Override
    protected String computeValue() {
        if (experiment.getRequestedStartTime() != null && experiment.getRequestedStartTime().isAfter(Instant.now())) {
            return composeReservationStartMessage();
        } else {
            return composeExpirationMessage();
        }
    }
}
