/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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 static org.onosproject.bgp.controller.BgpDpid.uri;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.Device.Type.ROUTER;
import static org.onosproject.net.Device.Type.VIRTUAL;
import static org.onosproject.incubator.net.resource.label.LabelResourceId.labelResourceId;
import static java.util.stream.Collectors.toList;

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

import org.onlab.packet.ChassisId;
import org.onlab.packet.Ip4Address;
import org.onlab.util.Bandwidth;
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
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.core.CoreService;
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.MastershipRole;
import org.onosproject.net.PortNumber;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.config.basics.BandwidthCapacity;
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.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 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_UNARY)
    protected DeviceProviderRegistry deviceProviderRegistry;

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

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

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected CoreService coreService;

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    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 void event(DeviceEvent event) {
            Device device = event.subject();

            switch (event.type()) {
                case DEVICE_ADDED:
                    if (!mastershipService.isLocalMaster(device.id())) {
                        break;
                    }

                    // Reserve device label pool for L3 devices
                    if (device.annotations().value(LSRID) != null) {
                        createDevicePool(device.id());
                    }
                    break;

                default:
                    break;
            }
        }
    }

    /*
     * 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 = new DefaultPortDescription(portNumber, true);
                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);

            //If already link exists, return
            if (linkService.getLink(linkDes.src(), linkDes.dst()) != null || linkProviderService == null) {
                return;
            }

            /*
             * 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())) {
                registerBandwidth(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(linkDes.src(), BandwidthCapacity.class);
                networkConfigService.removeConfig(linkDes.dst(), BandwidthCapacity.class);
            }

            linkProviderService.linkVanished(linkDes);

            linkDes = new DefaultLinkDescription(linkDes.dst(), linkDes.src(), Link.Type.DIRECT,
                    false, linkDes.annotations());
            linkProviderService.linkVanished(linkDes);
        }
    }

    // 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 registerBandwidth(LinkDescription linkDes, PathAttrNlriDetails details) {
        if (details ==  null) {
            log.error("Couldnot able 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();
        float maxReservableBw = 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;
            default: // do nothing
            }
        }

        if (maxReservableBw == 0.0) {
            return;
        }

        //Configure bandwidth for src and dst port
        BandwidthCapacity config = networkConfigService.addConfig(linkDes.src(), BandwidthCapacity.class);
        config.capacity(Bandwidth.bps(maxReservableBw)).apply();

        config = networkConfigService.addConfig(linkDes.dst(), BandwidthCapacity.class);
        config.capacity(Bandwidth.bps(maxReservableBw)).apply();
    }

    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;
        int igpMetric = 0;
        int teMetric = 0;
        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;
            case LinkStateAttributes.ATTR_LINK_IGP_METRIC:
                igpMetric = ((BgpLinkAttrIgpMetric) tlv).attrLinkIgpMetric();
                break;
            case LinkStateAttributes.ATTR_LINK_TE_DEFAULT_METRIC:
                teMetric = ((BgpLinkAttrTeDefaultMetric) tlv).attrLinkDefTeMetric();
                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));
            }
        } else {
            // Annotations for link
            if (igpMetric != 0) {
                annotationBuilder.set(COST, String.valueOf(igpMetric));
            }

            if (teMetric != 0) {
                annotationBuilder.set(TE_COST, String.valueOf(teMetric));
            }
        }
        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) {
    }
}
