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


import be.iminds.ilabt.jfed.lowlevel.TestbedInfoSource;
import be.iminds.ilabt.jfed.rspec.parser.ExtraXml;
import be.iminds.ilabt.jfed.util.GeniUrn;

import javax.annotation.Nullable;
import java.util.List;

/**
 * RspecLink
 */
public interface RspecLink {
    /**
     * replace all properties with the properties of another link
     * this assumes the relevant id's are the same.
     *
     * Useful when merging manifests.
     *
     * @param otherLink the other link, from which the properties have to be used
     * @param overwriteWithNulloverwriteNonAuthoratativeComponentManagers if true, set properties from this link to null, if they are null at otherLink and remove from list if not in otherLink's list.
     *                          If false, keep properties from this link unchanged, if they are null at otherLink and only add to lists.
     */
    void overwritePropertiesWith(RspecLink otherLink, boolean overwriteWithNulloverwriteNonAuthoratativeComponentManagers);

    ModelRspec getRspec();

    String getUniqueId();
    String getClientId();
    void setClientId(String value);

    //read write!
    List<GeniUrn> getComponentManagerUrns();

    List<String> getLinkTypes();

    List<? extends LinkSetting> getLinkSettings();
    LinkSetting getLinkSetting(RspecInterface fromIface, RspecInterface toIface);
    LinkSetting getLinkSettingByClientIds(String fromIfaceName, String toIfaceName);
    LinkSetting getLinkSettingByUniqueIds(String fromIfaceName, String toIfaceName);

    boolean isImpaired();

    /**
     * Interfaces are added to this list via RspecInterface. Deleting an interface is done by
     * {@link be.iminds.ilabt.jfed.rspec.model.javafx_impl.FXRspecInterface#delete()}
     *
     * @return
     */
    List<? extends RspecInterface> getInterfaces();
    RspecInterface getInterfaceForNode(RspecNode node);
    RspecInterface getInterfaceByUniqueId(String uniqueId);
    RspecInterface getInterfaceByClientId(String clientId);

    GeniUrn getSliverId();

    void setSliverId(String sliverId);
    void setSliverId(GeniUrn sliverId);

    /**
     * TestbedInfoSource is used to determine if two different URNs are actually the same authority.
     * This happens for exogeni for example. In that case, a link with multiple component managers can be a non-stitched link!
     *
     * if testbedInfoSource is null, it is assumed that any link (of type "lan") with multiple component managers is a stitched link
     *
     * note that only links of type "lan" can be stiched links. Links of type "egre" and "gre" are never stitched links.
     * */
    boolean isStitched(TestbedInfoSource testbedInfoSource);

    List<ExtraXml> getExtraXml();

    //sharedlan extension
    /**
     * @return null if no shared lan, shared lan name otherwise
     */
    String getSharedLan();
    void setSharedLan(String sharedLanName);


    Integer getVlanTag();
    void setVlanTag(Integer vlanTag);

    boolean isVlanTaggingEnabled();
    boolean hasVlanTaggingTag();
    /** set to null to remove tag completely */
    void setVlanTagging(Boolean value);

    boolean isNoMacLearning();
    boolean hasNoMacLearningTag();
    /** set to null to remove tag completely */
    void setNoMacLearning(Boolean value);
    /* very funny: can be "yep" instead of "true", and we should reconstruct it that way. */
    String getNoMacLeaningValueString();
    void setNoMacLearning(String value);

    boolean isBestEffortEnabled();

    boolean hasBestEffortTag();

    void setBestEffort(@Nullable Boolean value);

    boolean isLinkMultiplexingEnabled();

    boolean hasLinkMultiplexingTag();

    void setLinkMultiplexing(@Nullable Boolean value);

    boolean hasAutoShareLan();
    List<String> getAutoShareLanNames();

    boolean isInterswitchDisallowed();
    boolean hasInterswitchDisallowTag();
    void setInterswitchDisallow(@Nullable Boolean value);

}
