package be.iminds.ilabt.jfed.lowlevel.stitching;

import be.iminds.ilabt.jfed.util.TextUtil;
import be.iminds.ilabt.jfed.util.XmlUtil;
import org.w3c.dom.Element;

import java.util.ArrayList;
import java.util.List;

/**
 * AdvertisementStitchInfo: parse advertisement stitching info.

 example:
 <stitching xmlns="http://hpn.east.isi.edu/rspec/ext/stitch/0.1/" lastUpdateTime="2015-03-03T15:44:26Z">
 <aggregate id="urn:publicid:IDN+wall2.ilabt.iminds.be+authority+cm" url="https://www.wall2.ilabt.iminds.be:12369/protogeni/xmlrpc/am">
 <aggregatetype>protogeni</aggregatetype>
 <stitchingmode>chainANDTree</stitchingmode>
 <scheduledservices>false</scheduledservices>
 <negotiatedservices>false</negotiatedservices>
 <lifetime id="life">
 <start type="time">2015-03-03T15:44:26Z</start>
 <end type="time">2015-03-03T15:44:26Z</end>
 </lifetime>
 <node id="urn:publicid:IDN+wall2.ilabt.iminds.be+node+c300b">
 <port id="urn:publicid:IDN+wall2.ilabt.iminds.be+stitchport+c300b:0.12">
 <capacity>1000000</capacity>
 <maximumReservableCapacity>1000000</maximumReservableCapacity>
 <minimumReservableCapacity>1000</minimumReservableCapacity>
 <granularity>1</granularity>
 <link id="urn:publicid:IDN+wall2.ilabt.iminds.be+interface+c300b:0.12">
 <remoteLinkId>urn:publicid:IDN+ion.internet2.edu+interface+rtr.newy:xe-0/2/2:*</remoteLinkId>
 <trafficEngineeringMetric>10</trafficEngineeringMetric>
 <capacity>1000000</capacity>
 <maximumReservableCapacity>1000000</maximumReservableCapacity>
 <minimumReservableCapacity>1000</minimumReservableCapacity>
 <granularity>1</granularity>
 <switchingCapabilityDescriptor>
 <switchingcapType>l2sc</switchingcapType>
 <encodingType>ethernet</encodingType>
 <switchingCapabilitySpecificInfo>
 <switchingCapabilitySpecificInfo_L2sc>
 <interfaceMTU>1500</interfaceMTU>
 <vlanRangeAvailability>300-346,348-349</vlanRangeAvailability>
 <vlanTranslation>false</vlanTranslation>
 </switchingCapabilitySpecificInfo_L2sc>
 </switchingCapabilitySpecificInfo>
 </switchingCapabilityDescriptor>
 </link>
 </port>
 */
public class AdvertisementStitchInfo {
    private final String aggregateId;
    private final String aggregateUrl;
    private final String aggregateType;
    private final String nodeId;
    private final String portId;
    private final String linkId;
    private final String linkCapacity;
    private final String remoteLinkId;
    private final String vlanRangeAvailability;
    private final boolean vlanTranslation;

    private AdvertisementStitchInfo(String aggregateId, String aggregateUrl, String aggregateType,
                                    String nodeId, String portId, String linkId, String linkCapacity,
                                    String remoteLinkId, String vlanRangeAvailability,
                                    boolean vlanTranslation) {
        this.aggregateId = aggregateId;
        this.aggregateUrl = aggregateUrl;
        this.aggregateType = aggregateType;
        this.nodeId = nodeId;
        this.portId = portId;
        this.linkId = linkId;
        this.linkCapacity = linkCapacity;
        this.remoteLinkId = remoteLinkId;
        this.vlanRangeAvailability = vlanRangeAvailability;
        this.vlanTranslation = vlanTranslation;
    }

    public static List<AdvertisementStitchInfo> parse(String advertisementRspec) {
        List<AdvertisementStitchInfo> res = new ArrayList<>();

        Element stitchingElement = StitchingData.extractStitchingElementFromRspec(advertisementRspec);
        assert stitchingElement != null : "no stitching data in advertisement RSpec";

        List<Element> aggregateEls = XmlUtil.getDomElementChildElementsNS(stitchingElement, StitchingData.NAMESPACE_STITCHING, "aggregate");
        for (Element aggregateEl : aggregateEls) {
            String aggregateId = aggregateEl.getAttribute("id");
            String aggregateUrl = aggregateEl.getAttribute("url");
            String aggregateType = XmlUtil.getDomElementFirstChildElementText(aggregateEl, "aggregatetype");

            List<Element> nodeEls = XmlUtil.getDomElementChildElementsNS(stitchingElement, StitchingData.NAMESPACE_STITCHING, "node");
            for (Element nodeEl : nodeEls) {
                String nodeId = nodeEl.getAttribute("id");

                List<Element> portEls = XmlUtil.getDomElementChildElementsNS(stitchingElement, StitchingData.NAMESPACE_STITCHING, "port");
                for (Element portEl : portEls) {
                    String portId = portEl.getAttribute("id");

                    List<Element> linkEls = XmlUtil.getDomElementChildElementsNS(stitchingElement, StitchingData.NAMESPACE_STITCHING, "link");
                    for (Element linkEl : linkEls) {
                        String linkId = linkEl.getAttribute("id");

                        String linkCapacity = XmlUtil.getDomElementFirstChildElementText(linkEl, "capacity");
                        String remoteLinkId = XmlUtil.getDomElementFirstChildElementText(linkEl, "remoteLinkId");

                        Element scDescriptorEl = XmlUtil.getDomElementFirstChildElement(linkEl, "switchingCapabilityDescriptor");
                        Element scSpecificInfoEl = XmlUtil.getDomElementFirstChildElement(scDescriptorEl, "switchingCapabilitySpecificInfo");
                        Element scSpecificInfo_L2scEl = XmlUtil.getDomElementFirstChildElement(scSpecificInfoEl, "switchingCapabilitySpecificInfo_L2sc");
                        Element vlanRangeAvailabilityEl = XmlUtil.getDomElementFirstChildElement(scSpecificInfo_L2scEl, "vlanRangeAvailability");
                        Element vlanTranslationEl = XmlUtil.getDomElementFirstChildElement(scSpecificInfo_L2scEl, "vlanTranslation");
//                        Element suggestedVLANRangeEl = XmlUtil.getDomElementFirstChildElement(scSpecificInfo_L2scEl, "suggestedVLANRange");

                        String vlanRangeAvailability = vlanRangeAvailabilityEl.getTextContent();
                        boolean vlanTranslation = TextUtil.objectToBoolean(vlanTranslationEl.getTextContent()) == Boolean.TRUE;
//                        String suggestedVLANRange = suggestedVLANRangeEl.getTextContent();

                        res.add(new AdvertisementStitchInfo(aggregateId, aggregateUrl, aggregateType,
                                                            nodeId, portId, linkId, linkCapacity,
                                                            remoteLinkId, vlanRangeAvailability,
                                                            vlanTranslation));
                    }
                }
            }
        }

        return res;
    }

    public String getAggregateId() {
        return aggregateId;
    }

    public String getAggregateUrl() {
        return aggregateUrl;
    }

    public String getAggregateType() {
        return aggregateType;
    }

    public String getNodeId() {
        return nodeId;
    }

    public String getPortId() {
        return portId;
    }

    public String getLinkId() {
        return linkId;
    }

    public String getLinkCapacity() {
        return linkCapacity;
    }

    public String getRemoteLinkId() {
        return remoteLinkId;
    }

    public String getVlanRangeAvailability() {
        return vlanRangeAvailability;
    }

    public boolean isVlanTranslation() {
        return vlanTranslation;
    }
}
