package be.iminds.jfed.gts_highlevel.model;

import javafx.beans.property.*;
import javafx.collections.FXCollections;

import javax.xml.bind.annotation.XmlRootElement;
import java.util.Map;
import java.util.Objects;

/**
 * User: twalcari
 * Date: 9/17/2015
 * Time: 16:47
 */
@XmlRootElement(name="resourceBase")
public class GtsXmlResource {

    private final MapProperty<String, String> capabilities = new SimpleMapProperty<>();
    private final BooleanProperty failOnActivate = new SimpleBooleanProperty();
    private final BooleanProperty failOnDeactivate = new SimpleBooleanProperty();
    private final StringProperty id = new SimpleStringProperty();
    private final StringProperty providerId = new SimpleStringProperty();

    private final ObjectProperty<GtsXmlReservation> reservations=  new SimpleObjectProperty<>();
    private final ObjectProperty<GtsXmlReservation.Status> status = new SimpleObjectProperty<>();
    private final ObjectProperty<Type> type = new SimpleObjectProperty<>();

    private final MapProperty<String, Port> ports = new SimpleMapProperty<>();

    public Map<String, String> getCapabilities() {
        return capabilities.get();
    }

    public void setCapabilities(Map<String, String> capabilities) {
        this.capabilities.set(FXCollections.observableMap(capabilities));
    }

    public boolean isFailOnActivate() {
        return failOnActivate.get();
    }

    public boolean isFailOnDeactivate() {
        return failOnDeactivate.get();
    }

    public String getId() {
        return id.get();
    }

    public void setId(String id) {
        this.id.set(id);
    }

    public String getProviderId() {
        return providerId.get();
    }

    public void setProviderId(String providerId) {
        this.providerId.set(providerId);
    }

    public GtsXmlReservation getReservations() {
        return reservations.get();
    }

    public void setReservations(GtsXmlReservation reservations) {
        this.reservations.set(reservations);
    }

    public ObjectProperty<GtsXmlReservation> reservationsProperty() {
        return reservations;
    }

    public GtsXmlReservation.Status getStatus() {
        return status.get();
    }

    public void setStatus(GtsXmlReservation.Status status) {
        this.status.set(status);
    }

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

    public void setType(Type type) {
        this.type.set(type);
    }

    public MapProperty<String, String> capabilitiesProperty() {
        return capabilities;
    }

    public boolean getFailOnActivate() {
        return failOnActivate.get();
    }

    public void setFailOnActivate(boolean failOnActivate) {
        this.failOnActivate.set(failOnActivate);
    }

    public BooleanProperty failOnActivateProperty() {
        return failOnActivate;
    }

    public boolean getFailOnDeactive() {
        return failOnDeactivate.get();
    }

    public void setFailOnDeactivate(boolean failOnDeactivate) {
        this.failOnDeactivate.set(failOnDeactivate);
    }

    public BooleanProperty failOnDeactivateProperty() {
        return failOnDeactivate;
    }

    public StringProperty idProperty() {
        return id;
    }

    public MapProperty<String, Port> portsProperty() {
        return ports;
    }

    public StringProperty providerIdProperty() {
        return providerId;
    }

    public ObjectProperty<GtsXmlReservation.Status> statusProperty() {
        return status;
    }

    public ObjectProperty<Type> typeProperty() {
        return type;
    }

    public Map<String, Port> getPorts() {
        return ports.get();
    }

    public void setPorts(Map<String, Port> ports) {
        this.ports.set(FXCollections.observableMap(ports));
    }

    public static void copy(GtsXmlResource target, GtsXmlResource source){
        if(source == target)
            return; //we don't have to copy anything if source and target are the same
        if(!Objects.equals(target.getProviderId(), source.getProviderId()))
            throw new IllegalStateException("Copying info between objects with different provider ID's is not supported. (and is probably a bug).");

        target.id.set(source.id.get());
        target.capabilities.set(source.capabilities.get());
        target.failOnActivate.set(source.failOnActivate.get());
        target.failOnDeactivate.setValue(source.failOnDeactivate.get());
        target.ports.set(source.ports.get());
        target.reservations.set(source.reservations.get());
        target.status.set(source.status.get());
        target.type.set(source.type.get());
    }

    public enum Type {
        Host,
        Link,
        Testbed,
        OFX,
        ExternalDomain
    }

    public static class Port {
        private String id;
        private String connection;
        private String mode;
        private String parent;
        private Map<String,String> properties;
        private int version;
        private STP STP;

        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getConnection() {
            return connection;
        }

        public void setConnection(String connection) {
            this.connection = connection;
        }

        public String getMode() {
            return mode;
        }

        public void setMode(String mode) {
            this.mode = mode;
        }

        public String getParent() {
            return parent;
        }

        public void setParent(String parent) {
            this.parent = parent;
        }

        public Map<String, String> getProperties() {
            return properties;
        }

        public void setProperties(Map<String, String> properties) {
            this.properties = properties;
        }

        public int getVersion() {
            return version;
        }

        public void setVersion(int version) {
            this.version = version;
        }

        public Port.STP getSTP() {
            return STP;
        }

        public void setSTP(Port.STP STP) {
            this.STP = STP;
        }

        private static class STP {
            private String localId;
            private String networkId;
            private boolean remote;

            public String getLocalId() {
                return localId;
            }

            public void setLocalId(String localId) {
                this.localId = localId;
            }

            public String getNetworkId() {
                return networkId;
            }

            public void setNetworkId(String networkId) {
                this.networkId = networkId;
            }

            public boolean isRemote() {
                return remote;
            }

            public void setRemote(boolean remote) {
                this.remote = remote;
            }
        }

    }

    @Override
    public String toString() {
        return "GtsResource{" +
                "capabilities=" + capabilities +
                ", failOnActivate=" + failOnActivate +
                ", failOnDeactivate=" + failOnDeactivate +
                ", id=" + id +
                ", providerId=" + providerId +
                ", reservations=" + reservations +
                ", status=" + status +
                ", type=" + type +
                ", ports=" + ports +
                '}';
    }
}
