/*
 * Copyright 2016-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.tetopology.management.impl;

import static java.util.concurrent.Executors.newFixedThreadPool;
import static org.onlab.util.Tools.groupedThreads;
import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_ADDED;
import static org.onosproject.net.config.NetworkConfigEvent.Type.CONFIG_UPDATED;
import static org.onosproject.net.config.basics.SubjectFactories.APP_SUBJECT_FACTORY;
import static org.onosproject.tetopology.management.api.OptimizationType.NOT_OPTIMIZED;
import static org.onosproject.tetopology.management.api.TeTopology.BIT_CUSTOMIZED;
import static org.onosproject.tetopology.management.api.TeTopology.BIT_LEARNT;
import static org.onosproject.tetopology.management.api.TeTopology.BIT_MERGED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_REMOVED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.LINK_UPDATED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NETWORK_REMOVED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_REMOVED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.NODE_UPDATED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_REMOVED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_LINK_UPDATED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_REMOVED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_NODE_UPDATED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_ADDED;
import static org.onosproject.tetopology.management.api.TeTopologyEvent.Type.TE_TOPOLOGY_REMOVED;
import static org.onosproject.tetopology.management.api.link.TeLink.BIT_ACCESS_INTERDOMAIN;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.linkBuilder;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkBuilder;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkLinkKey;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.networkNodeKey;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.nodeBuilder;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.toNetworkId;
import static org.onosproject.tetopology.management.impl.TeMgrUtil.toNetworkLinkId;

import java.util.BitSet;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.MapUtils;
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.apache.felix.scr.annotations.Service;
import org.onlab.packet.Ip4Address;
import org.onosproject.app.ApplicationException;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.incubator.net.config.basics.ConfigException;
import org.onosproject.net.DeviceId;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.device.DeviceProviderRegistry;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.LinkProviderRegistry;
import org.onosproject.net.link.LinkService;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
import org.onosproject.net.provider.AbstractProviderService;
import org.onosproject.tetopology.management.api.CommonTopologyData;
import org.onosproject.tetopology.management.api.DefaultNetwork;
import org.onosproject.tetopology.management.api.DefaultNetworks;
import org.onosproject.tetopology.management.api.DefaultTeTopologies;
import org.onosproject.tetopology.management.api.DefaultTeTopology;
import org.onosproject.tetopology.management.api.KeyId;
import org.onosproject.tetopology.management.api.Network;
import org.onosproject.tetopology.management.api.Networks;
import org.onosproject.tetopology.management.api.TeConstants;
import org.onosproject.tetopology.management.api.TeTopologies;
import org.onosproject.tetopology.management.api.TeTopology;
import org.onosproject.tetopology.management.api.TeTopologyEvent;
import org.onosproject.tetopology.management.api.TeTopologyKey;
import org.onosproject.tetopology.management.api.TeTopologyListener;
import org.onosproject.tetopology.management.api.TeTopologyProvider;
import org.onosproject.tetopology.management.api.TeTopologyProviderRegistry;
import org.onosproject.tetopology.management.api.TeTopologyProviderService;
import org.onosproject.tetopology.management.api.TeTopologyService;
import org.onosproject.tetopology.management.api.link.CommonLinkData;
import org.onosproject.tetopology.management.api.link.DefaultTeLink;
import org.onosproject.tetopology.management.api.link.ExternalLink;
import org.onosproject.tetopology.management.api.link.LinkBandwidth;
import org.onosproject.tetopology.management.api.link.NetworkLink;
import org.onosproject.tetopology.management.api.link.NetworkLinkEventSubject;
import org.onosproject.tetopology.management.api.link.NetworkLinkKey;
import org.onosproject.tetopology.management.api.link.TeLink;
import org.onosproject.tetopology.management.api.link.TeLinkEventSubject;
import org.onosproject.tetopology.management.api.link.TeLinkTpGlobalKey;
import org.onosproject.tetopology.management.api.link.TeLinkTpKey;
import org.onosproject.tetopology.management.api.link.TePathAttributes;
import org.onosproject.tetopology.management.api.link.UnderlayPath;
import org.onosproject.tetopology.management.api.node.CommonNodeData;
import org.onosproject.tetopology.management.api.node.ConnectivityMatrix;
import org.onosproject.tetopology.management.api.node.DefaultTeNode;
import org.onosproject.tetopology.management.api.node.DefaultTunnelTerminationPoint;
import org.onosproject.tetopology.management.api.node.NetworkNode;
import org.onosproject.tetopology.management.api.node.NetworkNodeEventSubject;
import org.onosproject.tetopology.management.api.node.NetworkNodeKey;
import org.onosproject.tetopology.management.api.node.TeNode;
import org.onosproject.tetopology.management.api.node.TeNodeEventSubject;
import org.onosproject.tetopology.management.api.node.TeNodeKey;
import org.onosproject.tetopology.management.api.node.TerminationPoint;
import org.onosproject.tetopology.management.api.node.TerminationPointKey;
import org.onosproject.tetopology.management.api.node.TtpKey;
import org.onosproject.tetopology.management.api.node.TunnelTerminationPoint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.MoreObjects;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * Implementation of the topology management service.
 */
@Component(immediate = true)
@Service
public class TeTopologyManager
    extends AbstractListenerProviderRegistry<TeTopologyEvent, TeTopologyListener,
                                             TeTopologyProvider, TeTopologyProviderService>
    implements TeTopologyService, TeTopologyProviderRegistry {
    private static final String APP_NAME = "org.onosproject.tetopology";
    private static final long DEFAULT_PROVIDER_ID = 77777;
    private static final long DEFAULT_CLIENT_ID = 0x00L;
    private long providerId = DEFAULT_PROVIDER_ID;
    private static final int MAX_THREADS = 1;
    private static final Ip4Address DEFAULT_TENODE_ID_START = Ip4Address.valueOf("10.10.10.10");
    private static final Ip4Address DEFAULT_TENODE_ID_END = Ip4Address.valueOf("250.250.250.250");
    private Ip4Address teNodeIpStart = DEFAULT_TENODE_ID_START;
    private Ip4Address teNodeIpEnd = DEFAULT_TENODE_ID_END;
    private long nextTeNodeId = teNodeIpStart.toInt();
    private boolean mdsc = true;
    private static final String MDSC_MODE = "true";

    private final Logger log = LoggerFactory.getLogger(getClass());

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigRegistry cfgService;

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

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

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    public TeTopologyStore store;

    private TeTopologyStoreDelegate delegate = this::post;
    private final ConfigFactory<ApplicationId, TeTopologyConfig> factory =
            new ConfigFactory<ApplicationId, TeTopologyConfig>(APP_SUBJECT_FACTORY,
                    TeTopologyConfig.class,
                    "teTopologyCfg",
                    false) {
        @Override
        public TeTopologyConfig createConfig() {
            return new TeTopologyConfig();
        }
    };
    private final NetworkConfigListener cfgLister = new InternalConfigListener();
    private ApplicationId appId;
    // The topology merged in MDSC
    private TeTopology mergedTopology = null;
    private TeTopologyKey mergedTopologyKey;
    private Network mergedNetwork = null;
    // Track new TE node id by its source TE node key
    private Map<TeNodeKey, Long> sourceNewTeNodeIdMap = Maps.newHashMap();
    // Track the external link keys by the plugId
    private Map<Long, LinkKeyPair> externalLinkMap = Maps.newHashMap();
    private ExecutorService executor;

    /**
     * Activation helper function.
     */
    public void activateBasics() {
        store.setDelegate(delegate);
        store.setProviderId(providerId);
        eventDispatcher.addSink(TeTopologyEvent.class, listenerRegistry);
    }

    /**
     * Deactivation helper function.
     */
    public void deactivateBasics() {
        store.unsetDelegate(delegate);
        eventDispatcher.removeSink(TeTopologyEvent.class);
    }

    @Activate
    public void activate() {
        activateBasics();
        appId = coreService.registerApplication(APP_NAME);
        cfgService.registerConfigFactory(factory);
        executor = newFixedThreadPool(MAX_THREADS, groupedThreads("onos/tetopology", "build-%d", log));

        cfgService.addListener(cfgLister);
        executor.execute(new TopologyMergerTask());
        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        deactivateBasics();
        externalLinkMap.clear();
        cfgService.removeListener(cfgLister);
        cfgService.unregisterConfigFactory(factory);
        executor.shutdownNow();
        executor = null;
        log.info("Stopped");
    }

    @Override
    protected TeTopologyProviderService createProviderService(TeTopologyProvider provider) {
        return new InternalTopologyProviderService(provider);
    }

    private class InternalTopologyProviderService
                      extends AbstractProviderService<TeTopologyProvider>
                      implements TeTopologyProviderService {

        protected InternalTopologyProviderService(TeTopologyProvider provider) {
            super(provider);
        }

        @Override
        public void networkUpdated(Network network) {
            store.updateNetwork(network);
        }

        @Override
        public void networkRemoved(KeyId networkId) {
            store.removeNetwork(networkId);
        }

        @Override
        public void linkUpdated(NetworkLinkKey linkKey, NetworkLink link) {
            store.updateNetworkLink(linkKey, link);
        }

        @Override
        public void linkRemoved(NetworkLinkKey linkKey) {
            store.removeNetworkLink(linkKey);
        }

        @Override
        public void nodeUpdated(NetworkNodeKey nodeKey, NetworkNode node) {
            store.updateNetworkNode(nodeKey, node);
        }

        @Override
        public void nodeRemoved(NetworkNodeKey nodeKey) {
            store.removeNetworkNode(nodeKey);
        }

        @Override
        public void terminationPointUpdated(TerminationPointKey terminationPointKey,
                TerminationPoint terminationPoint) {
            store.updateTerminationPoint(terminationPointKey, terminationPoint);
        }

        @Override
        public void terminationPointRemoved(TerminationPointKey terminationPointKey) {
            store.removeTerminationPoint(terminationPointKey);
        }
    }

    private boolean isCustomizedLearnedTopology(TeTopologyKey key) {
        if (store.teTopology(key).flags().get(BIT_CUSTOMIZED) &&
                store.teTopology(key).flags().get(BIT_LEARNT)) {
            return true;
        }
        return false;
    }

    // Task for merge the learned topology.
    private class TopologyMergerTask implements Runnable {

        public TopologyMergerTask() {
        }

        @Override
        public void run() {
            try {
                TeTopologyMapEvent event;
                while ((event = store.mapEventQueue().take()) != null) {
                    switch (event.type()) {
                    case TE_TOPOLOGY_ADDED:
                    case TE_TOPOLOGY_UPDATED:
                        TeTopology teTopology = store.teTopology(event.teTopologyKey());
                        post(new TeTopologyEvent(event.type(), teTopology));
                        if (mdsc && event.type() == TE_TOPOLOGY_ADDED &&
                                teTopology.flags().get(BIT_CUSTOMIZED) &&
                                teTopology.flags().get(BIT_LEARNT)) {
                            log.debug("TeTopology to be merged: {}", teTopology);
                            mergeTopology(teTopology);
                        }
                        break;
                    case TE_TOPOLOGY_REMOVED:
                        post(new TeTopologyEvent(TE_TOPOLOGY_REMOVED,
                                                 new DefaultTeTopology(event.teTopologyKey(),
                                                                      null, null, null, null)));
                        break;
                    case TE_NODE_ADDED:
                    case TE_NODE_UPDATED:
                        if (store.teTopology(event.teNodeKey().teTopologyKey()) == null) {
                            // Event should be ignored when the topology is not there.
                            break;
                        }
                        TeNode teNode = store.teNode(event.teNodeKey());
                        post(new TeTopologyEvent(event.type(),
                                                 new TeNodeEventSubject(event.teNodeKey(), teNode)));
                        if (mdsc && isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
                            updateSourceTeNode(mergedTopology.teNodes(),
                                               event.teNodeKey().teTopologyKey(), teNode, true);
                        }
                        break;
                    case TE_NODE_REMOVED:
                        if (store.teTopology(event.teNodeKey().teTopologyKey()) == null) {
                            // Event should be ignored when the topology is not there.
                            break;
                        }
                        post(new TeTopologyEvent(TE_NODE_REMOVED,
                                                 new TeNodeEventSubject(event.teNodeKey(), null)));
                        if (mdsc && isCustomizedLearnedTopology(event.teNodeKey().teTopologyKey())) {
                            removeSourceTeNode(mergedTopology.teNodes(), event.teNodeKey(), true);
                        }
                        break;
                    case TE_LINK_ADDED:
                    case TE_LINK_UPDATED:
                        if (store.teTopology(event.teLinkKey().teTopologyKey()) == null ||
                                store.teNode(event.teLinkKey().teNodeKey()) == null) {
                            // Event should be ignored when the topology or node is not there.
                            break;
                        }
                        TeLink teLink = store.teLink(event.teLinkKey());
                        post(new TeTopologyEvent(event.type(),
                                                 new TeLinkEventSubject(event.teLinkKey(), teLink)));
                        if (mdsc && isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
                            Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
                            updateSourceTeLink(teLinks, event.teLinkKey().teTopologyKey(), teLink, true);
                            updateMergedTopology(mergedTopology.teNodes(), teLinks);
                        }
                        break;
                    case TE_LINK_REMOVED:
                        if (store.teTopology(event.teLinkKey().teTopologyKey()) == null ||
                                store.teNode(event.teLinkKey().teNodeKey()) == null) {
                            // Event should be ignored when the topology or node is not there.
                            break;
                        }
                        post(new TeTopologyEvent(TE_LINK_REMOVED,
                                                 new TeLinkEventSubject(event.teLinkKey(), null)));
                        if (mdsc && isCustomizedLearnedTopology(event.teLinkKey().teTopologyKey())) {
                            Map<TeLinkTpKey, TeLink> teLinks = Maps.newHashMap(mergedTopology.teLinks());
                            removeSourceTeLink(teLinks, event.teLinkKey(), true);
                            updateMergedTopology(mergedTopology.teNodes(), teLinks);
                        }
                        break;
                    case NETWORK_ADDED:
                    case NETWORK_UPDATED:
                        Network network = store.network(event.networkKey());
                        post(new TeTopologyEvent(event.type(), network));
                        break;
                    case NETWORK_REMOVED:
                        post(new TeTopologyEvent(NETWORK_REMOVED,
                                                 new DefaultNetwork(event.networkKey(), null, null,
                                                                    null, null, false, null,
                                                                    NOT_OPTIMIZED)));
                        break;
                    case NODE_ADDED:
                    case NODE_UPDATED:
                        if (store.network(event.networkNodeKey().networkId()) == null) {
                            // Event should be ignored when the network is not there.
                            break;
                        }
                        NetworkNode node = store.networkNode(event.networkNodeKey());
                        post(new TeTopologyEvent(event.type(),
                                                 new NetworkNodeEventSubject(event.networkNodeKey(), node)));
                        break;
                    case NODE_REMOVED:
                        if (store.network(event.networkNodeKey().networkId()) == null) {
                            // Event should be ignored when the network is not there.
                            break;
                        }
                        post(new TeTopologyEvent(NODE_REMOVED,
                                                 new NetworkNodeEventSubject(event.networkNodeKey(), null)));
                        break;
                    case LINK_ADDED:
                    case LINK_UPDATED:
                        if (store.network(event.networkLinkKey().networkId()) == null) {
                            // Event should be ignored when the network is not there.
                            break;
                        }
                        NetworkLink link = store.networkLink(event.networkLinkKey());
                        post(new TeTopologyEvent(event.type(),
                                                 new NetworkLinkEventSubject(event.networkLinkKey(), link)));
                        break;
                    case LINK_REMOVED:
                        if (store.network(event.networkLinkKey().networkId()) == null) {
                            // Event should be ignored when the network is not there.
                            break;
                        }
                        post(new TeTopologyEvent(LINK_REMOVED,
                                                 new NetworkLinkEventSubject(event.networkLinkKey(), null)));
                        break;
                    default:
                        break;
                    }
                }
            } catch (InterruptedException e) {
                log.warn("TopologyMergerTask is interrupted");
            } catch (Exception e) {
                log.warn("Unable to merge topology", e);
            }
        }
    }

    private void removeSourceTeNode(Map<Long, TeNode> teNodes,
                                    TeNodeKey srcNodeKey, boolean postEvent) {
        Long mergedTeNodeId = sourceNewTeNodeIdMap.remove(srcNodeKey);
        if (mergedTeNodeId == null) {
            return;
        }
        if (teNodes.remove(mergedTeNodeId) != null && postEvent) {
            TeNodeKey nodeKey = new TeNodeKey(mergedTopologyKey,
                                              mergedTeNodeId);
            post(new TeTopologyEvent(TE_NODE_REMOVED,
                                     new TeNodeEventSubject(nodeKey, null)));
            post(new TeTopologyEvent(NODE_REMOVED,
                                     new NetworkNodeEventSubject(TeMgrUtil
                                             .networkNodeKey(nodeKey), null)));
        }
    }

    private void updateSourceTeNode(Map<Long, TeNode> teNodes, TeTopologyKey srcTopoKey,
                                    TeNode srcNode, boolean postEvent) {
        TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey, srcNode.teNodeId());
        Long mergedTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeId);
        boolean addNode = false;
        if (mergedTeNodeId == null) {
            // New node
            addNode = true;
            mergedTeNodeId = nextTeNodeId;
            nextTeNodeId++;
            if (nextTeNodeId >= teNodeIpEnd.toInt()) {
                nextTeNodeId = teNodeIpStart.toInt();
                log.warn("TE node Id is wrapped back");
            }
            sourceNewTeNodeIdMap.put(sourceTeNodeId, mergedTeNodeId);
        }
        TeTopologyKey underlayTopologyId = null; // No underlay
        TeNodeKey supportTeNodeId = null; // No supporting

        CommonNodeData common = new CommonNodeData(srcNode.name(), srcNode.adminStatus(),
                                                   srcNode.opStatus(), srcNode.flags()); // No change
        Map<Long, ConnectivityMatrix> connMatrices = srcNode.connectivityMatrices();
        List<Long> teLinkIds = srcNode.teLinkIds(); // No change
        Map<Long, TunnelTerminationPoint> ttps = null;
        if (MapUtils.isNotEmpty(srcNode.tunnelTerminationPoints())) {
            ttps = Maps.newHashMap();
            for (Map.Entry<Long, TunnelTerminationPoint> entry : srcNode.tunnelTerminationPoints().entrySet()) {
                TunnelTerminationPoint ttp = entry.getValue();
                ttps.put(entry.getKey(),
                         new DefaultTunnelTerminationPoint(ttp.ttpId(), ttp.switchingLayer(),
                                                           ttp.encodingLayer(), ttp.flags(),
                                                           ttp.interLayerLockList(),
                                                           ttp.localLinkConnectivityList(),
                                                           ttp.availAdaptBandwidth(),
                                                           null)); //Remove supporting TTP Ids
            }
        }

        List<Long> teTpIds = srcNode.teTerminationPointIds(); // No change
        DefaultTeNode newNode = new DefaultTeNode(mergedTeNodeId, underlayTopologyId,
                supportTeNodeId, sourceTeNodeId, common, connMatrices, teLinkIds,
                ttps, teTpIds);
        teNodes.put(mergedTeNodeId, newNode);
        if (postEvent) {
            //Post event for the TE node in the merged topology
            TeNodeKey globalKey = new TeNodeKey(mergedTopologyKey, mergedTeNodeId);
            post(new TeTopologyEvent(addNode ? TE_NODE_ADDED : TE_NODE_UPDATED,
                                     new TeNodeEventSubject(globalKey, newNode)));
            post(new TeTopologyEvent(addNode ? NODE_ADDED : NODE_UPDATED,
                                     new NetworkNodeEventSubject(networkNodeKey(globalKey),
                                             nodeBuilder(KeyId.keyId(
                                                         Ip4Address.valueOf((int) newNode.teNodeId()).toString()),
                                                         newNode))));
        }
    }

    // Merge TE nodes
    private void mergeNodes(Map<Long, TeNode> nodes, TeTopology topology) {

        if (!MapUtils.isEmpty(topology.teNodes())) {
            for (Map.Entry<Long, TeNode> entry : topology.teNodes().entrySet()) {
                updateSourceTeNode(nodes, topology.teTopologyId(), entry.getValue(),
                                   mergedTopology != null);
            }
        }
    }

    // Returns a new TeLink based on an existing TeLink with new attributes
    private TeLink updateTeLink(TeLinkTpKey newKey, TeLinkTpKey peerTeLinkKey,
            TeTopologyKey underlayTopologyId, TeLinkTpGlobalKey supportTeLinkId,
            TeLinkTpGlobalKey sourceTeLinkId, ExternalLink externalLink,
            TeLink exLink) {
        UnderlayPath underlayPath = null;
        if (underlayTopologyId != null &&
                underlayTopologyId.equals(exLink.underlayTeTopologyId())) {
            underlayPath = new UnderlayPath(exLink.primaryPath(),
                                            exLink.backupPaths(), exLink.tunnelProtectionType(),
                                            exLink.sourceTtpId(), exLink.destinationTtpId(),
                                            exLink.teTunnelId()
                                            );
        }

        TePathAttributes teAttributes = new TePathAttributes(exLink.cost(),
                exLink.delay(), exLink.srlgs());
        LinkBandwidth bandwidth = new LinkBandwidth(exLink.maxBandwidth(),
                                                    exLink.availBandwidth(),
                                                    exLink.maxAvailLspBandwidth(),
                                                    exLink.minAvailLspBandwidth(),
                                                    exLink.oduResource());
        BitSet flags = exLink.flags();
        if (peerTeLinkKey != null &&
                externalLink != null && externalLink.plugId() != null) {
            // Assuming this is an inter-domain link which is merged with its peer,
            // needs to clear BIT_ACCESS_INTERDOMAIN
            flags.clear(BIT_ACCESS_INTERDOMAIN);
        } else if (peerTeLinkKey == null &&
                externalLink != null && externalLink.plugId() != null) {
            // Assuming this is an inter-domain link which lost its peer,
            // needs to clear BIT_ACCESS_INTERDOMAIN
            flags.set(BIT_ACCESS_INTERDOMAIN);
        }

        CommonLinkData common = new CommonLinkData(exLink.adminStatus(), exLink.opStatus(),
                flags, exLink.switchingLayer(), exLink.encodingLayer(),
                externalLink, underlayPath, teAttributes,
                exLink.administrativeGroup(), exLink.interLayerLocks(),
                bandwidth);
        return new DefaultTeLink(newKey, peerTeLinkKey, underlayTopologyId,
                supportTeLinkId, sourceTeLinkId, common);
    }

    private class LinkKeyPair {
        private TeLinkTpKey firstKey;
        private TeLinkTpKey secondKey;

        public LinkKeyPair(TeLinkTpKey firstKey) {
            this.firstKey = firstKey;
        }

        public TeLinkTpKey firstKey() {
            return firstKey;
        }

        public void setFirstKey(TeLinkTpKey firstKey) {
            this.firstKey = firstKey;
        }

        public TeLinkTpKey secondKey() {
            return secondKey;
        }

        public void setSecondKey(TeLinkTpKey secondKey) {
            this.secondKey = secondKey;
        }

        public boolean isFirstKey(TeLinkTpKey linkKey) {
            return firstKey == null ? false : firstKey.equals(linkKey);
        }

        public boolean isSecondKey(TeLinkTpKey linkKey) {
            return secondKey == null ? false : secondKey.equals(linkKey);
        }

        public boolean isEmpty() {
            return firstKey == null && secondKey == null;
        }

        @Override
        public String toString() {
            return MoreObjects.toStringHelper(this)
                    .add("firstKey", firstKey)
                    .add("secondKey", secondKey)
                    .toString();
        }
    }

    private void removeSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeLinkTpGlobalKey teLinkKey,
                                    boolean postEvent) {
        TeNodeKey sourceTeNodeKey = teLinkKey.teNodeKey();
        Long newTeNodeId = sourceNewTeNodeIdMap.get(sourceTeNodeKey);
        if (newTeNodeId == null) {
            return;
        }
        TeLinkTpKey newLinkKey = new TeLinkTpKey(newTeNodeId, teLinkKey.teLinkTpId());
        TeLink teLink = teLinks.remove(newLinkKey);
        if (teLink == null) {
            return;
        }
        //Post event
        if (postEvent) {
            TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
                                                                newLinkKey);
            post(new TeTopologyEvent(TE_LINK_REMOVED,
                                     new TeLinkEventSubject(globalKey, null)));
            post(new TeTopologyEvent(LINK_REMOVED,
                                     new NetworkLinkEventSubject(networkLinkKey(globalKey),
                                                                 null)));
        }

        if (teLink.externalLink() != null && teLink.externalLink().plugId() != null) {
            // Update the LinkKeyPair in externalLinkMap
            LinkKeyPair pair = externalLinkMap.get(teLink.externalLink().plugId());
            if (pair.isFirstKey(newLinkKey)) {
                pair.setFirstKey(null);
            } else if (pair.isSecondKey(newLinkKey)) {
                pair.setSecondKey(null);
            }
            if (pair.isEmpty()) {
                externalLinkMap.remove(teLink.externalLink().plugId());
            }
        }
        TeLinkTpKey peerTeLinkKey = teLink.peerTeLinkKey();
        if (peerTeLinkKey != null) {
            // Update peerLink's peerTeLinkKey to null
            TeLink peerLink = teLinks.get(peerTeLinkKey);
            if (peerLink == null || peerLink.peerTeLinkKey() == null) {
                return;
            }
            TeLink newPeerLink = updateTeLink(peerTeLinkKey, null,
                                       peerLink.underlayTeTopologyId(), peerLink.supportingTeLinkId(),
                                       peerLink.sourceTeLinkId(), peerLink.externalLink(), peerLink);
            teLinks.put(peerTeLinkKey, newPeerLink);
            if (postEvent) {
                TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
                                                                    peerTeLinkKey);
                post(new TeTopologyEvent(TE_LINK_UPDATED,
                                         new TeLinkEventSubject(globalKey,
                                                                newPeerLink)));
                post(new TeTopologyEvent(LINK_UPDATED,
                                         new NetworkLinkEventSubject(networkLinkKey(globalKey),
                                                                     linkBuilder(toNetworkLinkId(peerTeLinkKey),
                                                                                 newPeerLink))));
            }
        }
    }

    private void updateSourceTeLink(Map<TeLinkTpKey, TeLink> teLinks, TeTopologyKey srcTopoKey,
                                    TeLink srcLink, boolean postEvent) {
        TeNodeKey sourceTeNodeId = new TeNodeKey(srcTopoKey,
                                                 srcLink.teLinkKey().teNodeId());
        TeLinkTpKey newKey = new TeLinkTpKey(
                sourceNewTeNodeIdMap.get(sourceTeNodeId),
                srcLink.teLinkKey().teLinkTpId());
        TeLinkTpKey peerTeLinkKey = null;
        if (srcLink.peerTeLinkKey() != null) {
            TeNodeKey sourcePeerNode = new TeNodeKey(srcTopoKey,
                                                     srcLink.peerTeLinkKey().teNodeId());
            peerTeLinkKey = new TeLinkTpKey(
                    sourceNewTeNodeIdMap.get(sourcePeerNode),
                    srcLink.peerTeLinkKey().teLinkTpId());
        }

        if (srcLink.externalLink() != null &&
                srcLink.externalLink().plugId() != null) {
            // externalLinkKey doesn't have topology Id.
            // using plugId for now
            LinkKeyPair pair = externalLinkMap.get(srcLink.externalLink().plugId());
            if (pair == null) {
                // Store it in the map
                externalLinkMap.put(srcLink.externalLink().plugId(),
                                    new LinkKeyPair(newKey));
            } else {
                if (newKey.equals(pair.firstKey())) {
                    peerTeLinkKey = pair.secondKey();
                } else if (newKey.equals(pair.secondKey())) {
                    peerTeLinkKey = pair.firstKey();
                } else if (pair.firstKey() == null) {
                    peerTeLinkKey = pair.secondKey();
                    pair.setFirstKey(newKey);
                } else if (pair.secondKey() == null) {
                    peerTeLinkKey = pair.firstKey();
                    pair.setSecondKey(newKey);
                }

                if (peerTeLinkKey != null) {
                    TeLink peerLink = teLinks.get(peerTeLinkKey);
                    if (peerLink != null && (peerLink.peerTeLinkKey() == null
                            || !peerLink.peerTeLinkKey().equals(newKey))) {
                        // Update peer Link with local link key
                        TeLink newPeerLink = updateTeLink(peerTeLinkKey, newKey,
                                                          peerLink.underlayTeTopologyId(),
                                                          peerLink.supportingTeLinkId(),
                                                          peerLink.sourceTeLinkId(),
                                                          peerLink.externalLink(),
                                                          peerLink);
                        teLinks.put(peerTeLinkKey, newPeerLink);
                        if (postEvent) {
                            TeLinkTpGlobalKey globalKey = new TeLinkTpGlobalKey(mergedTopologyKey,
                                                                                peerTeLinkKey);
                            post(new TeTopologyEvent(TE_LINK_UPDATED,
                                                     new TeLinkEventSubject(globalKey,
                                                                            newPeerLink)));
                            post(new TeTopologyEvent(LINK_UPDATED,
                                                     new NetworkLinkEventSubject(
                                                             networkLinkKey(globalKey),
                                                             linkBuilder(toNetworkLinkId(peerTeLinkKey),
                                                                         newPeerLink))));
                        }
                    }
                }
            }
        }

        TeTopologyKey underlayTopologyId = null; // No underlay
        TeLinkTpGlobalKey supportTeLinkId = null; // No support
        // Source link for the new updated link
        TeLinkTpGlobalKey sourceTeLinkId = new TeLinkTpGlobalKey(srcTopoKey, srcLink.teLinkKey());
        TeLink updatedLink = updateTeLink(newKey, peerTeLinkKey, underlayTopologyId,
                                      supportTeLinkId, sourceTeLinkId,
                                      srcLink.externalLink(), srcLink);
        TeLinkTpGlobalKey newGlobalKey = new TeLinkTpGlobalKey(mergedTopologyKey, newKey);
        boolean newLink = teLinks.get(newKey) == null ? true : false;
        teLinks.put(newKey, updatedLink);
        if (postEvent) {
            //Post event
            post(new TeTopologyEvent(newLink ? TE_LINK_ADDED : TE_LINK_UPDATED,
                                     new TeLinkEventSubject(newGlobalKey, updatedLink)));
            post(new TeTopologyEvent(newLink ? LINK_ADDED : LINK_UPDATED,
                                     new NetworkLinkEventSubject(networkLinkKey(newGlobalKey),
                                             linkBuilder(toNetworkLinkId(updatedLink.teLinkKey()),
                                                         updatedLink))));
        }
    }

    // Merge TE links
    private void mergeLinks(Map<TeLinkTpKey, TeLink> teLinks, TeTopology topology) {
        if (!MapUtils.isEmpty(topology.teLinks())) {
            for (Map.Entry<TeLinkTpKey, TeLink> entry : topology.teLinks().entrySet()) {
                TeLink srcLink = entry.getValue();
                updateSourceTeLink(teLinks, topology.teTopologyId(), srcLink,
                                   mergedTopology != null);
            }
        }
    }

    // Update the merged topology with new TE nodes and links
    private void updateMergedTopology(Map<Long, TeNode> teNodes, Map<TeLinkTpKey, TeLink> teLinks) {
        boolean newTopology = mergedTopology == null;
        BitSet flags = newTopology ? new BitSet(TeConstants.FLAG_MAX_BITS) : mergedTopology.flags();
        flags.set(BIT_MERGED);
        CommonTopologyData commonData  = new CommonTopologyData(newTopology ?
                                                                toNetworkId(mergedTopologyKey) :
                                                                mergedTopology.networkId(),
                                                                NOT_OPTIMIZED,
                                                                flags, DeviceId.deviceId("localHost"));
        mergedTopology = new DefaultTeTopology(mergedTopologyKey, teNodes, teLinks,
                                               Long.toString(mergedTopologyKey.topologyId()), commonData);
        mergedNetwork = networkBuilder(mergedTopology);
        log.info("Nodes# {}, Links# {}", mergedTopology.teNodes().size(), mergedTopology.teLinks().size());
    }

    // Merge the new learned topology
    private void mergeTopology(TeTopology topology) {
        boolean newTopology = mergedTopology == null;
        mergedTopologyKey = newTopology ?
                            new TeTopologyKey(providerId, DEFAULT_CLIENT_ID,
                                              store.nextTeTopologyId()) :
                            mergedTopology.teTopologyId();

        Map<Long, TeNode> teNodes = newTopology || mergedTopology.teNodes() == null ?
                Maps.newHashMap() : Maps.newHashMap(mergedTopology.teNodes());
        mergeNodes(teNodes, topology);
        Map<TeLinkTpKey, TeLink> teLinks = newTopology || mergedTopology.teLinks() == null ?
                Maps.newHashMap() : Maps.newHashMap(mergedTopology.teLinks());
        mergeLinks(teLinks, topology);
        updateMergedTopology(teNodes, teLinks);
        log.debug("mergedTopology {}", mergedTopology);

        if (newTopology) {
            // Post events for the merged network topology;
            post(new TeTopologyEvent(TE_TOPOLOGY_ADDED, mergedTopology));
            post(new TeTopologyEvent(NETWORK_ADDED, mergedNetwork));
        }
    }

    private TeTopologyKey newTeTopologyKey(TeTopology teTopology) {
        TeTopologyKey key = teTopology.teTopologyId();
        if (key == null || teTopology.teTopologyIdStringValue() == null) {
            log.error("Ignoring the non-TE topology");
            throw new ApplicationException("Missing TE topology ID");
        }
        // Get the topologyId numeric value
        long idValue = key.topologyId();
        if (idValue == TeConstants.NIL_LONG_VALUE) {
            if (teTopology.teTopologyIdStringValue() != null) {
                try {
                    idValue = Long.parseLong(teTopology.teTopologyIdStringValue());
                } catch (NumberFormatException e) {
                    // Can't get the long value from the string.
                    // Use an assigned id value from local id pool,
                    idValue = store.nextTeTopologyId();
                }
                return new TeTopologyKey(key.providerId(), key.clientId(), idValue);
            }
        }
        return null;
    }

    private class InternalConfigListener implements NetworkConfigListener {

        @Override
        public void event(NetworkConfigEvent event) {
            try {
                providerId = cfgService.getConfig(appId, TeTopologyConfig.class)
                                       .providerId();
                store.setProviderId(providerId);
                teNodeIpStart = cfgService.getConfig(appId, TeTopologyConfig.class)
                                          .teNodeIpStart();
                teNodeIpEnd = cfgService.getConfig(appId, TeTopologyConfig.class)
                                        .teNodeIpEnd();
                mdsc = cfgService.getConfig(appId, TeTopologyConfig.class)
                        .mdsc().equals(MDSC_MODE);
                nextTeNodeId = teNodeIpStart.toInt();
            } catch (ConfigException e) {
                log.error("Configuration error {}", e);
            }
        }

        @Override
        public boolean isRelevant(NetworkConfigEvent event) {
            return event.configClass().equals(TeTopologyConfig.class) &&
                    (event.type() == CONFIG_ADDED ||
                    event.type() == CONFIG_UPDATED);
        }
    }

    @Override
    public TeTopologies teTopologies() {
        Map<TeTopologyKey, TeTopology> map;
        if (MapUtils.isNotEmpty(store.teTopologies().teTopologies())) {
            map = Maps.newHashMap(store.teTopologies().teTopologies());
        } else {
            map = Maps.newHashMap();
        }
        if (mergedTopology != null) {
            map.put(mergedTopologyKey, mergedTopology);
        }
        return new DefaultTeTopologies(store.teTopologies().name(), map);
    }

    @Override
    public TeTopology teTopology(TeTopologyKey topologyId) {
        if (mergedTopology != null &&
                topologyId != null &&
                topologyId.equals(mergedTopologyKey)) {
            return mergedTopology;
        }
        return store.teTopology(topologyId);
    }

    @Override
    public TeTopology mergedTopology() {
        return mergedTopology;
    }

    @Override
    public void updateTeTopology(TeTopology teTopology) {
        TeTopologyKey newKey = null;
        try {
            newKey = newTeTopologyKey(teTopology);
        } catch (ApplicationException e) {
            log.error("Ignoring the non-TE topology");
            return;
        }

        // TE topology is updated here from other APP or NBI, the flag
        // BIT_CUSTOMIZED or BIT_MERGED should be set.
        BitSet flags = teTopology.flags();
        if (flags == null ||
                !(flags.get(BIT_CUSTOMIZED) || flags.get(BIT_MERGED))) {
            log.error("TE topology flags {} are not set properly", flags);
            return;
        }

        if (newKey != null) {
            DefaultTeTopology newTopology = new DefaultTeTopology(
                    newKey == null ? teTopology.teTopologyId() : newKey,
                    teTopology.teNodes(), teTopology.teLinks(),
                    teTopology.teTopologyIdStringValue(), new CommonTopologyData(teTopology));
            // Update with new data
            store.updateTeTopology(newTopology);
        } else {
            store.updateTeTopology(teTopology);
        }
    }

    @Override
    public void removeTeTopology(TeTopologyKey topologyId) {
        store.removeTeTopology(topologyId);
    }

    @Override
    public Networks networks() {
        List<Network> networks;
        if (CollectionUtils.isNotEmpty(store.networks())) {
            networks = Lists.newArrayList(store.networks());
        } else {
            networks = Lists.newArrayList();
        }
        if (mergedNetwork != null) {
            networks.add(mergedNetwork);
        }
        return new DefaultNetworks(networks);
    }

    @Override
    public Network network(KeyId networkId) {
        if (mergedNetwork != null &&
                mergedNetwork.networkId().equals(networkId)) {
            return mergedNetwork;
        }
        return store.network(networkId);
    }

    @Override
    public void updateNetwork(Network network) {
        // TODO: This will be implemented if required.
    }

    @Override
    public void removeNetwork(KeyId networkId) {
        // TODO: This will be implemented if required.
    }

    @Override
    public TeNode teNode(TeNodeKey nodeId) {
        return nodeId.teTopologyKey().equals(mergedTopologyKey) ?
               mergedTopology.teNode(nodeId.teNodeId()) :
               store.teNode(nodeId);
    }

    @Override
    public TeLink teLink(TeLinkTpGlobalKey linkId) {
        return linkId.teTopologyKey().equals(mergedTopologyKey) ?
               mergedTopology.teLink(linkId.teLinkTpKey()) :
               store.teLink(linkId);
    }

    @Override
    public TunnelTerminationPoint tunnelTerminationPoint(TtpKey ttpId) {
        return ttpId.teTopologyKey().equals(mergedTopologyKey) ?
               mergedTopology.teNode(ttpId.teNodeId()).tunnelTerminationPoint(ttpId.ttpId()) :
               store.tunnelTerminationPoint(ttpId);
    }

    @Override
    public KeyId networkId(TeTopologyKey teTopologyKey) {
        return teTopologyKey.equals(mergedTopologyKey) ?
               mergedNetwork.networkId() :
               store.networkId(teTopologyKey);
    }

    @Override
    public NetworkNodeKey nodeKey(TeNodeKey teNodeKey) {
        return teNodeKey.teTopologyKey().equals(mergedTopologyKey) ?
               networkNodeKey(teNodeKey) :
               store.nodeKey(teNodeKey);
    }

    @Override
    public NetworkLinkKey linkKey(TeLinkTpGlobalKey teLinkKey) {
        return teLinkKey.teTopologyKey().equals(mergedTopologyKey) ?
               networkLinkKey(teLinkKey) :
               store.linkKey(teLinkKey);
    }

    @Override
    public TerminationPointKey terminationPointKey(TeLinkTpGlobalKey teTpKey) {
        return teTpKey.teTopologyKey().equals(mergedTopologyKey) ?
               new TerminationPointKey(networkNodeKey(teTpKey.teNodeKey()),
                                                      KeyId.keyId(Long.toString(teTpKey.teLinkTpId()))) :
               store.terminationPointKey(teTpKey);
    }

    @Override
    public long teContollerId() {
        return providerId;
    }
}
