package be.iminds.jfed.gts_highlevel.jobs.gts_parts;

import be.iminds.ilabt.jfed.experiment.Experiment;
import be.iminds.ilabt.jfed.experiment.ExperimentPart;
import be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXGeantTestbedType;
import be.iminds.jfed.gts_highlevel.controller.GtsModel;
import be.iminds.jfed.gts_highlevel.model.GtsXmlReservation;
import be.iminds.jfed.gts_highlevel.model.GtsXmlResource;
import be.iminds.jfed.gts_highlevel.model.GtsXmlType;
import javafx.beans.property.ReadOnlyObjectProperty;
import javafx.beans.property.ReadOnlyObjectWrapper;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Set;

/**
 * User: twalcari
 * Date: 1/12/2016
 * Time: 17:31
 */
public class GtsExperimentPart extends ExperimentPart {
    private final FXGeantTestbedType gtt;

    private final GtsModel model;
    private final ReadOnlyObjectWrapper<GtsXmlType> type = new ReadOnlyObjectWrapper<>();
    private final ReadOnlyObjectWrapper<GtsXmlReservation> reservation = new ReadOnlyObjectWrapper<>();
    private final ReadOnlyObjectWrapper<GtsXmlResource> resource = new ReadOnlyObjectWrapper<>();

//    private final MapChangeListener<String, GtsResource> modelResourcesListener =
//           change -> {
//                if (resource.get() != null && resource.get().getId().equals(change.getKey())) {
//                    resource.set(change.getValueAdded());
//                }
//            };
//    private final MapChangeListener<Integer, GtsReservation> modelReservationListener =
//            change -> {
//                if (reservation.get() != null && reservation.get().getId().equals(change.getKey())) {
//                    reservation.set(change.getValueAdded());
//                }
//            };


    public GtsExperimentPart(Experiment experiment, FXGeantTestbedType gtt, GtsModel model) {
        super(experiment);
        this.gtt = gtt;
        this.model = model;

//        this.model.getResources().addListener(new WeakMapChangeListener<>(modelResourcesListener));
//        this.model.getReservations().addListener(new WeakMapChangeListener<>(modelReservationListener));
    }

    @Override
    public String getName() {
        return "[GTS] " + gtt.getName();
    }

    /**
     * Can only be called once
     */
    public void registerResource(GtsXmlResource resource) {
        if (this.resource.get() != null)
            throw new IllegalStateException("GtsResource is already set in this GtsExperimentPart!");
        this.resource.set(resource);
    }

    public GtsXmlResource getResource() {
        return resource.get();
    }

    public ReadOnlyObjectProperty<GtsXmlResource> resourceProperty() {
        return resource.getReadOnlyProperty();
    }

    public Set<GtsXmlResource> getResourcesInReservation() {
        if (reservation.get() != null)
            return model.getResourcesInReservation(reservation.get());
        else
            return Collections.emptySet();
    }

    @Nonnull
    public FXGeantTestbedType getGeantTestbedType() {
        return gtt;
    }

    @Nullable
    public GtsXmlReservation getReservation() {
        return reservation.get();
    }

    public ReadOnlyObjectProperty<GtsXmlReservation> reservationProperty() {
        return reservation;
    }

    public void setReservation(GtsXmlReservation reservation) {
        this.reservation.set(reservation);
    }

    public GtsXmlType getType() {
        return type.get();
    }

    public ReadOnlyObjectProperty<GtsXmlType> typeProperty() {
        return type.getReadOnlyProperty();
    }

    /**
     * Can only be called once
     */
    public void registerType(GtsXmlType type) {
        if (this.type.get() != null)
            throw new IllegalStateException("GtsType is already set in this GtsExperimentPart!");
        this.type.set(type);
    }

    @Override
    public GtsExperimentPartsContainer getContainer() {
        return (GtsExperimentPartsContainer) super.getContainer();
    }
}
