package be.iminds.ilabt.jfed.highlevel.model;

import be.iminds.ilabt.jfed.lowlevel.AnyCredential;
import be.iminds.ilabt.jfed.lowlevel.SfaCredential;
import be.iminds.ilabt.jfed.util.JFedJavaFXBindings;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;

import javax.inject.Inject;
import javax.inject.Singleton;

/**
 * ParameterHistoryModel contains credentials, urns, and other info that is useful to fill in the fields of jFed Probe.
 * The SfaModel contains an instance and adds to it, and the user can also manually add to it.
 */
@Singleton
public class ParameterHistoryModel {


    private final ObservableList<AnyCredential> userCredentialInfos =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    private final ObservableList<AnyCredential> sliceCredentialInfos =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    private final ObservableList<AnyCredential> uncategorizedCredentiaInfos =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    private final ObservableList<String> sliceUrns =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    private final ObservableList<String> sliverUrns =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());
    private final ObservableList<String> userUrns =
            FXCollections.synchronizedObservableList(FXCollections.observableArrayList());


    @Inject
    public ParameterHistoryModel() {
    }

    public void seeUrn(String urn) {
        if (urn.startsWith("urn:publicid:IDN+")) {
            if (urn.contains("+user+"))
                addUserUrn(urn);
            if (urn.contains("+slice+"))
                addSliceUrn(urn);
            if (urn.contains("+sliver+"))
                addSliverUrn(urn);
        }
    }

    public void seeUrnsInCredential(AnyCredential credentialInfo) {
        try {
            if (credentialInfo instanceof SfaCredential) {
                seeUrn(((SfaCredential) credentialInfo).getTargetUrn());
                seeUrn(((SfaCredential) credentialInfo).getOwnerUrn());
            }
        } catch (Exception | AssertionError ignored) {
        } //ignore
    }

    public ObservableList<AnyCredential> getUserCredentialsList() {
        return userCredentialInfos;
    }

    public void addUserCredential(AnyCredential userCredentialInfo) {
        seeUrnsInCredential(userCredentialInfo);

        synchronized (userCredentialInfos) {
            if (!userCredentialInfos.contains(userCredentialInfo)) {
                userCredentialInfos.add(userCredentialInfo);
            }
        }
    }

    public ObservableList<AnyCredential> getSliceCredentialsList() {
        return sliceCredentialInfos;
    }

    public void addSliceCredential(AnyCredential sliceCredentialInfo) {
        seeUrnsInCredential(sliceCredentialInfo);
        synchronized (sliceCredentialInfos) {
            if (!sliceCredentialInfos.contains(sliceCredentialInfo))
                sliceCredentialInfos.add(sliceCredentialInfo);
        }
    }

    public ObservableList<AnyCredential> getUncategorizedCredentialsList() {
        return uncategorizedCredentiaInfos;
    }

    public void addUncategorizedCredential(AnyCredential uncategorizedCredentiaInfo) {
        seeUrnsInCredential(uncategorizedCredentiaInfo);
        synchronized (uncategorizedCredentiaInfos) {
            if (!uncategorizedCredentiaInfos.contains(uncategorizedCredentiaInfo))
                uncategorizedCredentiaInfos.add(uncategorizedCredentiaInfo);
        }
    }

    /**
     * getAnyCredentialsList
     *
     * @return the concatenation of the user, slice and uncategorized credential lists
     */
    public ObservableList<AnyCredential> getAnyCredentialsList() {
        //noinspection unchecked
        return JFedJavaFXBindings.union(userCredentialInfos, sliceCredentialInfos, uncategorizedCredentiaInfos);
    }

    public ObservableList<String> getAllUrnList() {
        //noinspection unchecked
        return JFedJavaFXBindings.union(sliceUrns, sliverUrns, userUrns);
    }

    public ObservableList<String> getSliceUrnsList() {
        return sliceUrns;
    }

    public void addSliceUrn(String urn) {
        synchronized (sliceUrns) {
            if (urn != null && !sliceUrns.contains(urn))
                sliceUrns.add(urn);
        }
    }

    public ObservableList<String> getSliverUrns() {
        return sliverUrns;
    }

    public void addSliverUrn(String urn) {
        synchronized (sliverUrns) {
            if (urn != null && !sliverUrns.contains(urn))
                sliverUrns.add(urn);
        }
    }

    public ObservableList<String> getUserUrns() {
        return userUrns;
    }

    public void addUserUrn(String urn) {
        synchronized (userUrns) {
            if (urn != null && !userUrns.contains(urn))
                userUrns.add(urn);
        }
    }
}
