/*
 * Copyright 2015-present Open Networking Foundation
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package org.onosproject.provider.bgp.topology.impl;

import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onosproject.bgp.controller.BgpController;
import org.onosproject.bgp.controller.BgpDpid;
import org.onosproject.bgp.controller.BgpLinkListener;
import org.onosproject.bgp.controller.BgpNodeListener;
import org.onosproject.bgpio.exceptions.BgpParseException;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpLinkLsNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSIdentifier;
import org.onosproject.bgpio.protocol.linkstate.BgpNodeLSNlriVer4;
import org.onosproject.bgpio.protocol.linkstate.NodeDescriptors;
import org.onosproject.bgpio.protocol.linkstate.PathAttrNlriDetails;
import org.onosproject.bgpio.types.AutonomousSystemTlv;
import org.onosproject.bgpio.types.BgpLSIdentifierTlv;
import org.onosproject.bgpio.types.BgpValueType;
import org.onosproject.bgpio.types.IPv4AddressTlv;
import org.onosproject.bgpio.types.IsIsNonPseudonode;
import org.onosproject.bgpio.types.IsIsPseudonode;
import org.onosproject.bgpio.types.LinkLocalRemoteIdentifiersTlv;
import org.onosproject.bgpio.types.LinkStateAttributes;
import org.onosproject.bgpio.types.OspfNonPseudonode;
import org.onosproject.bgpio.types.OspfPseudonode;
import org.onosproject.bgpio.types.attr.BgpAttrNodeFlagBitTlv;
import org.onosproject.bgpio.types.attr.BgpAttrNodeIsIsAreaId;
import org.onosproject.bgpio.types.attr.BgpAttrRouterIdV4;
import org.onosproject.bgpio.types.attr.BgpLinkAttrIgpMetric;
import org.onosproject.bgpio.types.attr.BgpLinkAttrMaxLinkBandwidth;
import org.onosproject.bgpio.types.attr.BgpLinkAttrTeDefaultMetric;
import org.onosproject.bgpio.types.attr.BgpLinkAttrUnRsrvdLinkBandwidth;
import org.onosproject.incubator.net.resource.label.LabelResourceAdminService;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
import org.onosproject.net.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.device.DefaultDeviceDescription;
import org.onosproject.net.device.DefaultPortDescription;
import org.onosproject.net.device.DeviceDescription;
import org.onosproject.net.device.DeviceEvent;
import org.onosproject.net.device.DeviceListener;
import org.onosproject.net.device.DeviceProvider;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceProviderService;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.device.PortDescription;
import org.onosproject.net.link.DefaultLinkDescription;
import org.onosproject.net.link.LinkDescription;
import org.onosproject.net.link.LinkProvider;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkProviderService;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pcep.api.TeLinkConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;

import static java.util.stream.Collectors.toList;
import static org.onosproject.bgp.controller.BgpDpid.uri;
import static org.onosproject.incubator.net.resource.label.LabelResourceId.labelResourceId;
import static org.onosproject.net.Device.Type.ROUTER;
import static org.onosproject.net.Device.Type.VIRTUAL;
import static org.onosproject.net.DeviceId.deviceId;

/**
 * Provider which uses an BGP controller to detect network infrastructure topology.
 */
@Component(immediate = true)
public class BgpTopologyProvider extends AbstractProvider implements DeviceProvider, LinkProvider {

    /**
     * Creates an instance of BGP topology provider.
     */
    public BgpTopologyProvider() {
        super(new ProviderId("l3", "org.onosproject.provider.bgp"));
    }

    private static final Logger log = LoggerFactory.getLogger(BgpTopologyProvider.class);

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceProviderRegistry deviceProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkProviderRegistry linkProviderRegistry;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected BgpController controller;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LinkService linkService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected MastershipService mastershipService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected LabelResourceAdminService labelResourceAdminService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected NetworkConfigService networkConfigService;

    private DeviceProviderService deviceProviderService;
    private LinkProviderService linkProviderService;

    private DeviceListener deviceListener = new InternalDeviceListener();
    private InternalBgpProvider listener = new InternalBgpProvider();
    private static final String UNKNOWN = "unknown";
    public static final long IDENTIFIER_SET = 0x100000000L;
    public static final String AS_NUMBER = "asNumber";
    public static final String DOMAIN_IDENTIFIER = "domainIdentifier";
    public static final String ROUTING_UNIVERSE = "routingUniverse";

    public static final String EXTERNAL_BIT = "externalBit";
    public static final String ABR_BIT = "abrBit";
    public static final String INTERNAL_BIT = "internalBit";
    public static final String PSEUDO = "psuedo";
    public static final String AREAID = "areaId";
    public static final String LSRID = "lsrId";
    public static final String COST = "cost";
    public static final String TE_COST = "teCost";

    public static final long PSEUDO_PORT = 0xffffffff;
    public static final int DELAY = 2;
    private LabelResourceId beginLabel = labelResourceId(5122);
    private LabelResourceId endLabel = labelResourceId(9217);
    private HashMap<DeviceId, List<PortDescription>> portMap = new HashMap<>();

    @Activate
    public void activate() {
        log.debug("BgpTopologyProvider activate");
        deviceProviderService = deviceProviderRegistry.register(this);
        linkProviderService = linkProviderRegistry.register(this);
        controller.addListener(listener);
        deviceService.addListener(deviceListener);
        controller.addLinkListener(listener);
    }

    @Deactivate
    public void deactivate() {
        log.debug("BgpTopologyProvider deactivate");
        deviceProviderRegistry.unregister(this);
        deviceProviderService = null;
        linkProviderRegistry.unregister(this);
        linkProviderService = null;
        controller.removeListener(listener);
        controller.removeLinkListener(listener);
        deviceService.removeListener(deviceListener);
    }

    private class InternalDeviceListener implements DeviceListener {
        @Override
        public boolean isRelevant(DeviceEvent event) {
            return event.type() == DeviceEvent.Type.DEVICE_ADDED &&
                    mastershipService.isLocalMaster(event.subject().id());
        }

        @Override
        public void event(DeviceEvent event) {
            Device device = event.subject();
            // Reserve device label pool for L3 devices
            if (device.annotations().value(LSRID) != null) {
                createDevicePool(device.id());
            }
        }
    }

    /*
     * Implements device and link update.
     */
    private class InternalBgpProvider implements BgpNodeListener, BgpLinkListener {

        @Override
        public void addNode(BgpNodeLSNlriVer4 nodeNlri, PathAttrNlriDetails details) {
            log.debug("Add node {}", nodeNlri.toString());

            if (deviceProviderService == null || deviceService == null) {
                return;
            }
            Device.Type deviceType = ROUTER;
            BgpDpid nodeUri = new BgpDpid(nodeNlri);
            DeviceId deviceId = deviceId(uri(nodeUri.toString()));
            ChassisId cId = new ChassisId();

            /*
             * Check if device is already there (available) , if yes not updating to core.
             */
            if (deviceService.isAvailable(deviceId)) {
                return;
            }

            DefaultAnnotations.Builder newBuilder = DefaultAnnotations.builder();

            newBuilder.set(AnnotationKeys.TYPE, "L3");
            newBuilder.set(ROUTING_UNIVERSE, Long.toString(nodeNlri.getIdentifier()));

            List<BgpValueType> tlvs = nodeNlri.getLocalNodeDescriptors().getNodedescriptors().getSubTlvs();
            for (BgpValueType tlv : tlvs) {
                if (tlv instanceof AutonomousSystemTlv) {
                    newBuilder.set(AS_NUMBER, Integer.toString(((AutonomousSystemTlv) tlv).getAsNum()));
                } else if (tlv instanceof BgpLSIdentifierTlv) {
                    newBuilder.set(DOMAIN_IDENTIFIER,
                            Integer.toString(((BgpLSIdentifierTlv) tlv).getBgpLsIdentifier()));
                }
                if (tlv.getType() == NodeDescriptors.IGP_ROUTERID_TYPE) {
                    if (tlv instanceof IsIsPseudonode) {
                        deviceType = VIRTUAL;
                        newBuilder.set(AnnotationKeys.ROUTER_ID, nodeUri.isoNodeIdString(((IsIsPseudonode) tlv)
                                .getIsoNodeId()));
                    } else if (tlv instanceof OspfPseudonode) {
                        deviceType = VIRTUAL;
                        newBuilder
                                .set(AnnotationKeys.ROUTER_ID, Integer.toString(((OspfPseudonode) tlv).getrouterID()));
                    } else if (tlv instanceof IsIsNonPseudonode) {
                        newBuilder.set(AnnotationKeys.ROUTER_ID, nodeUri.isoNodeIdString(((IsIsNonPseudonode) tlv)
                                .getIsoNodeId()));
                    } else if (tlv instanceof OspfNonPseudonode) {
                        newBuilder.set(AnnotationKeys.ROUTER_ID,
                                Integer.toString(((OspfNonPseudonode) tlv).getrouterID()));
                    }
                }
            }
            DefaultAnnotations.Builder anntotations = DefaultAnnotations.builder();
            anntotations = getAnnotations(newBuilder, true, details);

            DeviceDescription description = new DefaultDeviceDescription(uri(nodeUri.toString()), deviceType, UNKNOWN,
                    UNKNOWN, UNKNOWN, UNKNOWN, cId, anntotations.build());

            deviceProviderService.deviceConnected(deviceId, description);
        }

        @Override
        public void deleteNode(BgpNodeLSNlriVer4 nodeNlri) {
            log.debug("Delete node {}", nodeNlri.toString());

            if (deviceProviderService == null) {
                return;
            }

            BgpDpid deviceUri = new BgpDpid(nodeNlri);
            DeviceId deviceId = deviceId(uri(deviceUri.toString()));

            if (labelResourceAdminService != null) {
                //Destroy local device label pool reserved for that device
                labelResourceAdminService.destroyDevicePool(deviceId);
            }

            deviceProviderService.deviceDisconnected(deviceId);
        }

        private List<PortDescription> buildPortDescriptions(DeviceId deviceId,
                                                            PortNumber portNumber) {

            List<PortDescription> portList;

            if (portMap.containsKey(deviceId)) {
                portList = portMap.get(deviceId);
            } else {
                portList = new ArrayList<>();
            }
            if (portNumber != null) {
                PortDescription portDescriptions = DefaultPortDescription.builder().withPortNumber(portNumber)
                        .isEnabled(true).build();
                portList.add(portDescriptions);
            }

            portMap.put(deviceId, portList);
            return portList;
        }

        @Override
        public void addLink(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details) throws BgpParseException {
            log.debug("Addlink {}", linkNlri.toString());

            LinkDescription linkDes = buildLinkDes(linkNlri, details, true);



            /*
             * Update link ports and configure bandwidth on source and destination port using networkConfig service
             * Only master of source link registers for bandwidth
             */
            if (mastershipService.isLocalMaster(linkDes.src().deviceId())) {
                registerBandwidthAndTeMetric(linkDes, details);
            }

            //Updating ports of the link
            deviceProviderService.updatePorts(linkDes.src().deviceId(), buildPortDescriptions(linkDes.src().deviceId(),
                    linkDes.src().port()));

            deviceProviderService.updatePorts(linkDes.dst().deviceId(), buildPortDescriptions(linkDes.dst().deviceId(),
                    linkDes.dst().port()));

            linkProviderService.linkDetected(linkDes);
        }

        //Build link description.
        private LinkDescription buildLinkDes(BgpLinkLsNlriVer4 linkNlri, PathAttrNlriDetails details, boolean isAddLink)
                throws BgpParseException {
            long srcAddress = 0;
            long dstAddress = 0;
            boolean localPseduo = false;
            boolean remotePseduo = false;

            List<BgpValueType> localTlvs = linkNlri.getLinkIdentifier().localNodeDescriptors().getSubTlvs();
            for (BgpValueType localTlv : localTlvs) {
                if (localTlv instanceof IsIsPseudonode || localTlv instanceof OspfPseudonode) {
                    localPseduo = true;
                }
            }
            List<BgpValueType> remoteTlvs = linkNlri.getLinkIdentifier().remoteNodeDescriptors().getSubTlvs();
            for (BgpValueType remoteTlv : remoteTlvs) {
                if (remoteTlv instanceof IsIsPseudonode || remoteTlv instanceof OspfPseudonode) {
                    remotePseduo = true;
                }
            }

            List<BgpValueType> tlvs = linkNlri.getLinkIdentifier().linkDescriptors();
            for (BgpValueType tlv : tlvs) {
                if (tlv instanceof LinkLocalRemoteIdentifiersTlv) {
                    srcAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkLocalIdentifier();
                    //Set 32nd bit.
                    srcAddress = srcAddress | IDENTIFIER_SET;
                    dstAddress = ((LinkLocalRemoteIdentifiersTlv) tlv).getLinkRemoteIdentifier();
                    dstAddress = dstAddress | IDENTIFIER_SET;
                } else if (tlv instanceof IPv4AddressTlv) {
                    if (tlv.getType() == BgpLinkLSIdentifier.IPV4_INTERFACE_ADDRESS_TYPE) {
                        srcAddress = ((IPv4AddressTlv) tlv).address().toInt();
                    } else {
                        dstAddress = ((IPv4AddressTlv) tlv).address().toInt();
                    }
                }
            }

            DeviceId srcId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_LOCAL).toString()));
            DeviceId dstId = deviceId(uri(new BgpDpid(linkNlri, BgpDpid.NODE_DESCRIPTOR_REMOTE).toString()));

            if (localPseduo && srcAddress == 0) {
                srcAddress = PSEUDO_PORT;
            } else if (remotePseduo && dstAddress == 0) {
                dstAddress = PSEUDO_PORT;
            }

            ConnectPoint src = new ConnectPoint(srcId, PortNumber.portNumber(srcAddress));
            ConnectPoint dst = new ConnectPoint(dstId, PortNumber.portNumber(dstAddress));
            BgpNodeLSNlriVer4 srcNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
                    .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().localNodeDescriptors()), false,
                    linkNlri.getRouteDistinguisher());

            BgpNodeLSNlriVer4 dstNodeNlri = new BgpNodeLSNlriVer4(linkNlri.getIdentifier(), linkNlri.getProtocolId()
                    .getType(), new BgpNodeLSIdentifier(linkNlri.getLinkIdentifier().remoteNodeDescriptors()), false,
                    linkNlri.getRouteDistinguisher());

            addOrDeletePseudoNode(isAddLink, localPseduo, remotePseduo, srcNodeNlri,
                     dstNodeNlri, srcId, dstId, details);
            DefaultAnnotations.Builder annotationBuilder = DefaultAnnotations.builder();
            if (details != null) {
                annotationBuilder = getAnnotations(annotationBuilder, false, details);
            }

            return new DefaultLinkDescription(src, dst, Link.Type.DIRECT, false, annotationBuilder.build());
        }

        private void addOrDeletePseudoNode(boolean isAddLink, boolean localPseduo, boolean remotePseduo,
                BgpNodeLSNlriVer4 srcNodeNlri, BgpNodeLSNlriVer4 dstNodeNlri, DeviceId srcId, DeviceId dstId,
                PathAttrNlriDetails details) {
            if (isAddLink) {
                if (localPseduo) {
                    if (deviceService.getDevice(srcId) == null) {
                        for (BgpNodeListener l : controller.listener()) {
                            l.addNode(srcNodeNlri, details);
                        }
                    }
                } else if (remotePseduo) {
                    if (deviceService.getDevice(dstId) == null) {
                        for (BgpNodeListener l : controller.listener()) {
                            l.addNode(dstNodeNlri, details);
                        }
                    }
                }
            } else {
                if (localPseduo) {
                    Set<Link> links = linkService.getDeviceLinks(srcId);
                    if (links == null || links.isEmpty()) {
                        for (BgpNodeListener l : controller.listener()) {
                            l.deleteNode(srcNodeNlri);
                        }
                    }
                } else if (remotePseduo) {
                    log.info("Remote pseudo delete link ");
                    Set<Link> links = linkService.getDeviceLinks(dstId);
                    if (links == null || links.isEmpty()) {
                        for (BgpNodeListener l : controller.listener()) {
                            l.deleteNode(dstNodeNlri);
                        }
                    }
                }
            }
        }

        @Override
        public void deleteLink(BgpLinkLsNlriVer4 linkNlri) throws BgpParseException {
            log.debug("Delete link {}", linkNlri.toString());

            if (linkProviderService == null) {
                return;
            }

            LinkDescription linkDes = buildLinkDes(linkNlri, null, false);

            /*
             * Only master for the link src will release the bandwidth resource.
             */
            if (networkConfigService != null && mastershipService.isLocalMaster(linkDes.src().deviceId())) {
                // Releases registered resource for this link
                networkConfigService.removeConfig(LinkKey.linkKey(linkDes.src(), linkDes.dst()), TeLinkConfig.class);
            }

            linkProviderService.linkVanished(linkDes);

            linkDes = new DefaultLinkDescription(linkDes.dst(), linkDes.src(), Link.Type.DIRECT,
                    false, linkDes.annotations());
            linkProviderService.linkVanished(linkDes);
            if (networkConfigService != null && mastershipService.isLocalMaster(linkDes.src().deviceId())) {
                // Releases registered resource for this link
                networkConfigService.removeConfig(LinkKey.linkKey(linkDes.src(), linkDes.dst()), TeLinkConfig.class);
            }

        }
    }

    // Creates label resource pool for the specific device. For all devices label range is 5122-9217
    private void createDevicePool(DeviceId deviceId) {
        if (labelResourceAdminService == null) {
            return;
        }

        labelResourceAdminService.createDevicePool(deviceId, beginLabel, endLabel);
    }

    private void registerBandwidthAndTeMetric(LinkDescription linkDes, PathAttrNlriDetails details) {
        if (details ==  null) {
            log.error("Unable to register bandwidth ");
            return;
        }

        List<BgpValueType> attribute = details.pathAttributes().stream()
                .filter(attr -> attr instanceof LinkStateAttributes).collect(toList());
        if (attribute.isEmpty()) {
            return;
        }

        List<BgpValueType> tlvs = ((LinkStateAttributes) attribute.iterator().next()).linkStateAttributes();
        double maxReservableBw = 0;
        List<Float>  unreservedBw = new ArrayList<>();
        int teMetric = 0;
        int igpMetric = 0;

        for (BgpValueType tlv : tlvs) {
            switch (tlv.getType()) {
            case LinkStateAttributes.ATTR_LINK_MAX_RES_BANDWIDTH:
                maxReservableBw = ((BgpLinkAttrMaxLinkBandwidth) tlv).linkAttrMaxLinkBandwidth();
                //will get in bits/second , convert to MBPS to store in network config service
                maxReservableBw = maxReservableBw / 1000000;
                break;
            case LinkStateAttributes.ATTR_LINK_UNRES_BANDWIDTH:
                unreservedBw = ((BgpLinkAttrUnRsrvdLinkBandwidth) tlv).getLinkAttrUnRsrvdLinkBandwidth();
                break;
            case LinkStateAttributes.ATTR_LINK_TE_DEFAULT_METRIC:
                teMetric = ((BgpLinkAttrTeDefaultMetric) tlv).attrLinkDefTeMetric();
                break;
            case LinkStateAttributes.ATTR_LINK_IGP_METRIC:
                igpMetric = ((BgpLinkAttrIgpMetric) tlv).attrLinkIgpMetric();
                break;
            default: // do nothing
            }
        }

        //Configure bandwidth for src and dst port
        TeLinkConfig config = networkConfigService.addConfig(LinkKey.linkKey(linkDes.src(), linkDes.dst()),
                                                             TeLinkConfig.class);
        Double bw = 0.0;
        if (unreservedBw.size() > 0) {
            bw = unreservedBw.get(0).doubleValue(); //Low priority
        }

        config.maxResvBandwidth(maxReservableBw)
                .unResvBandwidth(bw).teCost(teMetric).igpCost(igpMetric);
                //.apply();

        networkConfigService.applyConfig(LinkKey.linkKey(linkDes.src(),
                linkDes.dst()), TeLinkConfig.class, config.node());
    }

    private DefaultAnnotations.Builder getAnnotations(DefaultAnnotations.Builder annotationBuilder, boolean isNode,
            PathAttrNlriDetails details) {

        List<BgpValueType> attribute = details.pathAttributes().stream()
                .filter(attr -> attr instanceof LinkStateAttributes).collect(toList());
        if (attribute.isEmpty()) {
            return annotationBuilder;
        }
        List<BgpValueType> tlvs = ((LinkStateAttributes) attribute.iterator().next()).linkStateAttributes();
        boolean abrBit = false;
        boolean externalBit = false;
        boolean pseudo = false;
        byte[] areaId = null;
        Ip4Address routerId = null;
        for (BgpValueType tlv : tlvs) {
            switch (tlv.getType()) {
            case LinkStateAttributes.ATTR_NODE_FLAG_BITS:
                abrBit = ((BgpAttrNodeFlagBitTlv) tlv).abrBit();
                externalBit = ((BgpAttrNodeFlagBitTlv) tlv).externalBit();
                break;
            case NodeDescriptors.IGP_ROUTERID_TYPE:
                if (tlv instanceof IsIsPseudonode || tlv instanceof OspfPseudonode) {
                    pseudo = true;
                }
                break;
            case LinkStateAttributes.ATTR_NODE_ISIS_AREA_ID:
                areaId = ((BgpAttrNodeIsIsAreaId) tlv).attrNodeIsIsAreaId();
                break;
            case LinkStateAttributes.ATTR_NODE_IPV4_LOCAL_ROUTER_ID:
                routerId = ((BgpAttrRouterIdV4) tlv).attrRouterId();
                break;
            default: // do nothing
            }
        }

        // Annotations for device
        if (isNode) {
            boolean internalBit = false;
            if (!abrBit && !externalBit) {
                internalBit = true;
            }

            annotationBuilder.set(EXTERNAL_BIT, String.valueOf(externalBit));
            annotationBuilder.set(ABR_BIT, String.valueOf(abrBit));
            annotationBuilder.set(INTERNAL_BIT, String.valueOf(internalBit));
            annotationBuilder.set(PSEUDO, String.valueOf(pseudo));

            if (areaId != null) {
                annotationBuilder.set(AREAID, new String(areaId));
            }
            if (routerId != null) {
                // LsrID
                annotationBuilder.set(LSRID, String.valueOf(routerId));
            }
        }
        return annotationBuilder;
    }

    @Override
    public void triggerProbe(DeviceId deviceId) {
        // TODO Auto-generated method stub
    }

    @Override
    public void roleChanged(DeviceId deviceId, MastershipRole newRole) {
    }

    @Override
    public boolean isReachable(DeviceId deviceId) {
        // TODO Auto-generated method stub
        return true;
    }

    @Override
    public void changePortState(DeviceId deviceId, PortNumber portNumber,
                                boolean enable) {
    }
}
