/*
 * 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.pce.pceservice;

import static com.google.common.base.Preconditions.checkNotNull;

import org.onosproject.net.DisjointPath;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
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.IpAddress;
import org.onlab.util.Bandwidth;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.core.IdGenerator;
import org.onosproject.incubator.net.tunnel.DefaultTunnel;
import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
import org.onosproject.incubator.net.tunnel.TunnelEvent;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelListener;
import org.onosproject.incubator.net.tunnel.TunnelName;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.mastership.MastershipService;
import org.onosproject.net.LinkKey;
import org.onosproject.net.config.ConfigFactory;
import org.onosproject.net.config.NetworkConfigRegistry;
import org.onosproject.net.config.NetworkConfigService;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path;
import org.onosproject.net.config.basics.SubjectFactories;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intent.Constraint;
import org.onosproject.net.link.LinkEvent;
import org.onosproject.net.MastershipRole;
import org.onosproject.bandwidthmgr.api.BandwidthMgmtService;
import org.onosproject.pce.pceservice.constraint.CapabilityConstraint;
import org.onosproject.pce.pceservice.constraint.CapabilityConstraint.CapabilityType;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.constraint.PceBandwidthConstraint;
import org.onosproject.pce.pceservice.constraint.SharedBandwidthConstraint;
import org.onosproject.net.resource.Resource;
import org.onosproject.net.resource.ResourceAllocation;
import org.onosproject.net.topology.LinkWeight;
import org.onosproject.net.topology.PathService;
import org.onosproject.net.topology.TopologyEdge;
import org.onosproject.net.topology.TopologyEvent;
import org.onosproject.net.topology.TopologyListener;
import org.onosproject.net.topology.TopologyService;
import org.onosproject.pce.pceservice.api.PceService;
import org.onosproject.pce.pcestore.PcePathInfo;
import org.onosproject.pce.pcestore.api.PceStore;
import org.onosproject.pcep.api.DeviceCapability;
import org.onosproject.pcep.api.TeLinkConfig;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.StorageService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;

import static org.onosproject.incubator.net.tunnel.Tunnel.State.INIT;
import static org.onosproject.incubator.net.tunnel.Tunnel.State.UNSTABLE;
import static org.onosproject.incubator.net.tunnel.Tunnel.Type.MPLS;
import static org.onosproject.pce.pceservice.LspType.WITH_SIGNALLING;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.BANDWIDTH;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LOCAL_LSP_ID;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.LSP_SIG_TYPE;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCE_INIT;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PLSP_ID;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.PCC_TUNNEL_ID;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.DELEGATE;
import static org.onosproject.pce.pceservice.PcepAnnotationKeys.COST_TYPE;

/**
 * Implementation of PCE service.
 */
@Component(immediate = true)
@Service
public class PceManager implements PceService {
    private static final Logger log = LoggerFactory.getLogger(PceManager.class);

    public static final long GLOBAL_LABEL_SPACE_MIN = 4097;
    public static final long GLOBAL_LABEL_SPACE_MAX = 5121;
    public static final String PCE_SERVICE_APP = "org.onosproject.pce";
    private static final String LOCAL_LSP_ID_GEN_TOPIC = "pcep-local-lsp-id";
    public static final String DEVICE_TYPE = "type";
    public static final String L3_DEVICE = "L3";

    private static final String LSRID = "lsrId";
    private static final String TRUE = "true";
    private static final String FALSE = "false";
    public static final int PCEP_PORT = 4189;

    private IdGenerator localLspIdIdGen;
    protected DistributedSet<Short> localLspIdFreeList;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PathService pathService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PceStore pceStore;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TunnelService tunnelService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected StorageService storageService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected NetworkConfigService netCfgService;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TopologyService topologyService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected BandwidthMgmtService bandwidthMgmtService;

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

    private TunnelListener listener = new InnerTunnelListener();
    private ApplicationId appId;

    private final TopologyListener topologyListener = new InternalTopologyListener();
    public static final String LOAD_BALANCING_PATH_NAME = "loadBalancingPathName";

    private List<TunnelId> rsvpTunnelsWithLocalBw = new ArrayList<>();

    private final ConfigFactory<LinkKey, TeLinkConfig> configFactory =
            new ConfigFactory<LinkKey, TeLinkConfig>(SubjectFactories.LINK_SUBJECT_FACTORY,
                    TeLinkConfig.class, "teLinkConfig") {
                @Override
                public TeLinkConfig createConfig() {
                    return new TeLinkConfig();
                }
            };

    /**
     * Creates new instance of PceManager.
     */
    public PceManager() {
    }

    @Activate
    protected void activate() {
        appId = coreService.registerApplication(PCE_SERVICE_APP);

        tunnelService.addListener(listener);

        localLspIdIdGen = coreService.getIdGenerator(LOCAL_LSP_ID_GEN_TOPIC);
        localLspIdIdGen.getNewId(); // To prevent 0, the 1st value generated from being used in protocol.
        localLspIdFreeList = storageService.<Short>setBuilder()
                .withName("pcepLocalLspIdDeletedList")
                .withSerializer(Serializer.using(KryoNamespaces.API))
                .build()
                .asDistributedSet();

        topologyService.addListener(topologyListener);
        netConfigRegistry.registerConfigFactory(configFactory);

        log.info("Started");
    }

    @Deactivate
    protected void deactivate() {
        tunnelService.removeListener(listener);
        topologyService.removeListener(topologyListener);
        netConfigRegistry.unregisterConfigFactory(configFactory);

        log.info("Stopped");
    }

    /**
     * Returns an edge-weight capable of evaluating links on the basis of the
     * specified constraints.
     *
     * @param constraints path constraints
     * @return edge-weight function
     */
    private LinkWeight weight(List<Constraint> constraints) {
        return new TeConstraintBasedLinkWeight(constraints);
    }

    /**
     * Computes a path between two devices.
     *
     * @param src ingress device
     * @param dst egress device
     * @param constraints path constraints
     * @return computed path based on constraints
     */
    protected Set<Path> computePath(DeviceId src, DeviceId dst, List<Constraint> constraints) {
        if (pathService == null) {
            return ImmutableSet.of();
        }

        Set<Path> paths = pathService.getPaths(src, dst, weight(constraints));
        log.info("paths in computePath ::" + paths);
        if (!paths.isEmpty()) {
            return paths;
        }
        return ImmutableSet.of();
    }

    //Computes the partial path from partial computed path to specified dst.
    private List<Path> computePartialPath(List<Path> computedPath, DeviceId src, DeviceId dst,
                                    List<Constraint> constraints) {
        int size = computedPath.size();
        Path path = null;
        DeviceId deviceId = size == 0 ? src :
                computedPath.get(size - 1).dst().deviceId();

        Set<Path> tempComputePath = computePath(deviceId, dst, constraints);

        if (tempComputePath.isEmpty()) {
            return null;
        }

        //if path validation fails return null
        //Validate computed path to avoid loop in the path
        for (Path p : tempComputePath) {
            if (pathValidation(computedPath, p)) {
                path = p;
                break;
            }
        }
        if (path == null) {
            return null;
        }

        //Store the partial path result in a list
        computedPath.add(path);
        return computedPath;
    }

    private List<DeviceId> createListOfDeviceIds(List<? extends NetworkResource> list) {
        List<Link> links = new LinkedList<>();
        if (!list.isEmpty() && list.iterator().next() instanceof Path) {
            for (Path path : (List<Path>) list) {
                links.addAll(path.links());
            }
        } else if (!list.isEmpty() && list.iterator().next() instanceof Link) {
            links.addAll((List<Link>) list);
        }

        //List of devices for new path computed
        DeviceId source = null;
        DeviceId destination = null;
        List<DeviceId> devList = new LinkedList<>();

        for (Link l : links) {
            if (!devList.contains(l.src().deviceId())) {
                devList.add(l.src().deviceId());
            }
            if (!devList.contains(l.dst().deviceId())) {
                devList.add(l.dst().deviceId());
            }
        }

        return devList;
    }

    //To detect loops in the path i.e if the partial paths has intersection node avoid it.
    private boolean pathValidation(List<Path> partialPath, Path path) {

        //List of devices in new path computed
        List<DeviceId> newPartialPathDevList;
        newPartialPathDevList = createListOfDeviceIds(path.links());

        //List of devices in partial computed path
        List<DeviceId> partialComputedPathDevList;
        partialComputedPathDevList = createListOfDeviceIds(partialPath);

        for (DeviceId deviceId : newPartialPathDevList) {
            for (DeviceId devId : partialComputedPathDevList) {
                if (!newPartialPathDevList.get(0).equals(deviceId) &&
                        !partialComputedPathDevList.get(partialComputedPathDevList.size() - 1).equals(devId)
                        && deviceId.equals(devId)) {
                    return false;
                }
            }
        }
        return true;
    }

    //Returns final computed explicit path (list of partial computed paths).
    private List<Path> computeExplicitPath(List<ExplicitPathInfo> explicitPathInfo, DeviceId src, DeviceId dst,
            List<Constraint> constraints) {
        List<Path> finalComputedPath = new LinkedList<>();
        for (ExplicitPathInfo info : explicitPathInfo) {
            /*
             * If explicit path object is LOOSE,
             * 1) If specified as DeviceId (node) :
             * If it is source , compute from source to destination (partial computation not required),
             * otherwise compute from specified source to specified device
             * 2) If specified as Link :
             * Compute partial path from source to link's source , if path exists compute from link's source to dst
             */
            if (info.type().equals(ExplicitPathInfo.Type.LOOSE)) {
                if (info.value() instanceof DeviceId) {
                    // If deviceId is source no need to compute
                    if (!(info.value()).equals(src)) {
                        log.debug("computeExplicitPath :: Loose , device");
                        finalComputedPath = computePartialPath(finalComputedPath, src, (DeviceId) info.value(),
                                constraints);
                        log.debug("finalComputedPath in computeExplicitPath ::" + finalComputedPath);
                    }

                } else if (info.value() instanceof Link) {
                    if ((((Link) info.value()).src().deviceId().equals(src))
                            || (!finalComputedPath.isEmpty()
                            && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(
                                    ((Link) info.value()).src().deviceId()))) {

                        finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).dst()
                                .deviceId(), constraints);
                    } else {

                        finalComputedPath = computePartialPath(finalComputedPath, src, ((Link) info.value()).src()
                                .deviceId(), constraints) != null ? computePartialPath(finalComputedPath, src,
                                ((Link) info.value()).dst().deviceId(), constraints) : null;
                    }
                }
                /*
                 * If explicit path object is STRICT,
                 * 1) If specified as DeviceId (node) :
                 * Check whether partial computed path has reachable to strict specified node orde
                 * strict node is the source, if no set path as null else do nothing
                 * 2) If specified as Link :
                 * Check whether partial computed path has reachable to strict link's src, if yes compute
                 * path from strict link's src to link's dst (to include specified link)
                 */
            } else if (info.type().equals(ExplicitPathInfo.Type.STRICT)) {
                if (info.value() instanceof DeviceId) {
                    log.debug("computeExplicitPath :: Strict , device");
                    if (!(!finalComputedPath.isEmpty() && finalComputedPath.get(finalComputedPath.size() - 1).dst()
                            .deviceId().equals(info.value()))
                            && !info.value().equals(src)) {
                        finalComputedPath = null;
                    }

                } else if (info.value() instanceof Link) {
                    log.info("computeExplicitPath :: Strict");
                    finalComputedPath = ((Link) info.value()).src().deviceId().equals(src)
                            || !finalComputedPath.isEmpty()
                            && finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId()
                                    .equals(((Link) info.value()).src().deviceId()) ? computePartialPath(
                            finalComputedPath, src, ((Link) info.value()).dst().deviceId(), constraints) : null;

                    //Log.info("computeExplicitPath :: (Link) info.value() " + (Link) info.value());
                    //Log.info("computeExplicitPath :: finalComputedPath " + finalComputedPath);

                    if (finalComputedPath != null && !finalComputedPath.get(finalComputedPath.size() - 1).links()
                            .contains((Link) info.value())) {
                        finalComputedPath = null;
                    }
                }
            }
            if (finalComputedPath == null) {
                return null;
            }
        }
        // Destination is not reached in Partial computed path then compute till destination
        if (finalComputedPath.isEmpty() || !finalComputedPath.isEmpty()
                && !finalComputedPath.get(finalComputedPath.size() - 1).dst().deviceId().equals(dst)) {

            finalComputedPath = computePartialPath(finalComputedPath, src, dst, constraints);
            if (finalComputedPath == null) {
                return null;
            }
        }

        return finalComputedPath;
    }

    @Override
    public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
                             LspType lspType) {
        return setupPath(src, dst, tunnelName, constraints, lspType, null, false);
    }

    //[TODO:] handle requests in queue
    @Override
    public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
                             LspType lspType, List<ExplicitPathInfo> explicitPathInfo) {
        return setupPath(src, dst, tunnelName, constraints, lspType, explicitPathInfo, false);

    }

    @Override
    public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
                             LspType lspType, boolean loadBalancing) {
        return setupPath(src, dst, tunnelName, constraints, lspType, null, loadBalancing);
    }

    @Override
    public boolean setupPath(DeviceId src, DeviceId dst, String tunnelName, List<Constraint> constraints,
                             LspType lspType, List<ExplicitPathInfo> explicitPathInfo, boolean loadBalancing) {
        checkNotNull(src);
        checkNotNull(dst);
        checkNotNull(tunnelName);
        checkNotNull(lspType);

        // Convert from DeviceId to TunnelEndPoint
        Device srcDevice = deviceService.getDevice(src);
        Device dstDevice = deviceService.getDevice(dst);

        if (srcDevice == null || dstDevice == null) {
            // Device is not known.
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
                    loadBalancing));
            return false;
        }

        // In future projections instead of annotations will be used to fetch LSR ID.
        String srcLsrId = srcDevice.annotations().value(LSRID);
        String dstLsrId = dstDevice.annotations().value(LSRID);

        if (srcLsrId == null || dstLsrId == null) {
            // LSR id is not known.
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
                    loadBalancing));
            return false;
        }

        // Get device config from netconfig, to ascertain that session with ingress is present.
        DeviceCapability cfg = netCfgService.getConfig(DeviceId.deviceId(srcLsrId), DeviceCapability.class);
        if (cfg == null) {
            log.debug("No session to ingress.");
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
                    loadBalancing));
            return false;
        }

        TunnelEndPoint srcEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(srcLsrId));
        TunnelEndPoint dstEndPoint = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(dstLsrId));

        double bwConstraintValue = 0;
        CostConstraint costConstraint = null;
        if (constraints != null) {
            constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
            Iterator<Constraint> iterator = constraints.iterator();

            while (iterator.hasNext()) {
                Constraint constraint = iterator.next();
                if (constraint instanceof PceBandwidthConstraint) {
                    bwConstraintValue = ((PceBandwidthConstraint) constraint).bandwidth().bps();
                } else if (constraint instanceof CostConstraint) {
                    costConstraint = (CostConstraint) constraint;
                }
            }

            /*
             * Add cost at the end of the list of constraints. The path computation algorithm also computes cumulative
             * cost. The function which checks the limiting/capability constraints also returns per link cost. This
             * function can either return the result of limiting/capability constraint validation or the value of link
             * cost, depending upon what is the last constraint in the loop.
             */
            if (costConstraint != null) {
                constraints.remove(costConstraint);
                constraints.add(costConstraint);
            }
        } else {
            constraints = new LinkedList<>();
            constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspType.name())));
        }
        Set<Path> computedPathSet = Sets.newLinkedHashSet();

        if (loadBalancing) {
            return setupDisjointPaths(src, dst, constraints, tunnelName, bwConstraintValue, lspType, costConstraint,
                    srcEndPoint, dstEndPoint);
        }

        if (explicitPathInfo != null && !explicitPathInfo.isEmpty()) {
            List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo, src, dst, constraints);
            if (finalComputedPath == null) {
                return false;
            }

            pceStore.tunnelNameExplicitPathInfoMap(tunnelName, explicitPathInfo);
            List<Link> links = new LinkedList<>();
            double totalCost = 0;
            // Add all partial computed paths
            for (Path path : finalComputedPath) {
                links.addAll(path.links());
                totalCost = totalCost + path.cost();
            }
            computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(), links, totalCost));
        } else {
            computedPathSet = computePath(src, dst, constraints);
        }

        // NO-PATH
        if (computedPathSet.isEmpty()) {
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
                    loadBalancing));
            return false;
        }

        Builder annotationBuilder = DefaultAnnotations.builder();
        if (bwConstraintValue != 0) {
            annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
        }
        if (costConstraint != null) {
            annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
        }
        annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
        annotationBuilder.set(PCE_INIT, TRUE);
        annotationBuilder.set(DELEGATE, TRUE);

        Path computedPath = computedPathSet.iterator().next();

        if (lspType != WITH_SIGNALLING) {
            /*
             * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
             * PCE for non-RSVP signalled LSPs.
             */
            annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
        }

        // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
        Tunnel tunnel = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
                                          TunnelName.tunnelName(tunnelName), computedPath,
                                          annotationBuilder.build());

        // Allocate bandwidth for all tunnels.
        if (bwConstraintValue != 0) {
            if (!reserveBandwidth(computedPath, bwConstraintValue, null)) {
                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints,
                        lspType, explicitPathInfo, loadBalancing));
                return false;
            }
        }

        TunnelId tunnelId = tunnelService.setupTunnel(appId, src, tunnel, computedPath);
        if (tunnelId == null) {
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, explicitPathInfo,
                    loadBalancing));

            if (bwConstraintValue != 0) {
                computedPath.links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
                        Double.parseDouble(tunnel.annotations().value(BANDWIDTH))));
            }

            return false;
        }

        if (bwConstraintValue != 0 && lspType == WITH_SIGNALLING) {
            rsvpTunnelsWithLocalBw.add(tunnelId);
        }

        return true;
    }

    private boolean setupDisjointPaths(DeviceId src, DeviceId dst, List<Constraint> constraints, String tunnelName,
                                       double bwConstraintValue, LspType lspType, CostConstraint costConstraint,
                                       TunnelEndPoint srcEndPoint, TunnelEndPoint dstEndPoint) {
        Set<DisjointPath> paths = pathService.getDisjointPaths(src, dst, weight(constraints));

        // NO-PATH
        if (paths.isEmpty()) {
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));
            return false;
        }

        DisjointPath path = paths.iterator().next();

        Builder annotationBuilder = DefaultAnnotations.builder();
        double bw = 0;
        if (bwConstraintValue != 0) {
            //TODO: BW needs to be divided by 2 :: bwConstraintValue/2
            bw = bwConstraintValue / 2;
            annotationBuilder.set(BANDWIDTH, String.valueOf(bw));
        }
        if (costConstraint != null) {
            annotationBuilder.set(COST_TYPE, String.valueOf(costConstraint.type()));
        }
        annotationBuilder.set(LSP_SIG_TYPE, lspType.name());
        annotationBuilder.set(PCE_INIT, TRUE);
        annotationBuilder.set(DELEGATE, TRUE);
        annotationBuilder.set(LOAD_BALANCING_PATH_NAME, tunnelName);

        //Path computedPath = computedPathSet.iterator().next();

        if (lspType != WITH_SIGNALLING) {
            /*
             * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
             * PCE for non-RSVP signalled LSPs.
             */
            annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(getNextLocalLspId()));
        }

        //Generate different tunnel name for disjoint paths
        String tunnel1 = (new StringBuilder()).append(tunnelName).append("_1").toString();
        String tunnel2 = (new StringBuilder()).append(tunnelName).append("_2").toString();

        // For SR-TE tunnels, call SR manager for label stack and put it inside tunnel.
        Tunnel tunnelPrimary = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
                TunnelName.tunnelName(tunnel1), path.primary(),
                annotationBuilder.build());

        Tunnel tunnelBackup = new DefaultTunnel(null, srcEndPoint, dstEndPoint, MPLS, INIT, null, null,
                TunnelName.tunnelName(tunnel2), path.backup(),
                annotationBuilder.build());

        // Allocate bandwidth.
        if (bwConstraintValue != 0) {
            if (!reserveBandwidth(path.primary(), bw, null)) {
                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnel1, constraints,
                                                           lspType, null, true));
                return false;
            }

            if (!reserveBandwidth(path.backup(), bw, null)) {
                //Release bandwidth resource for tunnel1
                if (bwConstraintValue != 0) {
                    path.primary().links().forEach(ln ->
                                         bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
                                         Double.parseDouble(tunnelPrimary.annotations().value(BANDWIDTH))));
                }

                pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnel2, constraints,
                                                           lspType, null, true));
                return false;
            }
        }

        TunnelId tunnelId1 = tunnelService.setupTunnel(appId, src, tunnelPrimary, path.primary());
        if (tunnelId1 == null) {
            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));

            if (bwConstraintValue != 0) {
                path.primary().links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
                                                   Double.parseDouble(tunnelPrimary.annotations().value(BANDWIDTH))));
            }

            return false;
        }

        TunnelId tunnelId2 = tunnelService.setupTunnel(appId, src, tunnelBackup, path.backup());
        if (tunnelId2 == null) {
            //Release 1st tunnel
            releasePath(tunnelId1);

            pceStore.addFailedPathInfo(new PcePathInfo(src, dst, tunnelName, constraints, lspType, null, true));

            if (bwConstraintValue != 0) {
                path.backup().links().forEach(ln -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(ln),
                                                    Double.parseDouble(tunnelBackup.annotations().value(BANDWIDTH))));
            }

            return false;
        }

        pceStore.addLoadBalancingTunnelIdsInfo(tunnelName, tunnelId1, tunnelId2);
        //pceStore.addDisjointPathInfo(tunnelName, path);
        return true;
    }

    @Override
    public boolean updatePath(TunnelId tunnelId, List<Constraint> constraints) {
        checkNotNull(tunnelId);
        Set<Path> computedPathSet = Sets.newLinkedHashSet();
        Tunnel tunnel = tunnelService.queryTunnel(tunnelId);

        if (tunnel == null) {
            return false;
        }

        if (tunnel.type() != MPLS || FALSE.equalsIgnoreCase(tunnel.annotations().value(DELEGATE))) {
            // Only delegated LSPs can be updated.
            return false;
        }

        List<Link> links = tunnel.path().links();
        String lspSigType = tunnel.annotations().value(LSP_SIG_TYPE);
        double bwConstraintValue = 0;
        String costType = null;
        SharedBandwidthConstraint shBwConstraint = null;
        PceBandwidthConstraint bwConstraint = null;
        CostConstraint costConstraint = null;

        if (constraints != null) {
            // Call path computation in shared bandwidth mode.
            Iterator<Constraint> iterator = constraints.iterator();
            while (iterator.hasNext()) {
                Constraint constraint = iterator.next();
                if (constraint instanceof PceBandwidthConstraint) {
                    bwConstraint = (PceBandwidthConstraint) constraint;
                    bwConstraintValue = bwConstraint.bandwidth().bps();
                } else if (constraint instanceof CostConstraint) {
                    costConstraint = (CostConstraint) constraint;
                    costType = costConstraint.type().name();
                }
            }

            // Remove and keep the cost constraint at the end of the list of constraints.
            if (costConstraint != null) {
                constraints.remove(costConstraint);
            }

            Bandwidth existingBwValue = null;
            String existingBwAnnotation = tunnel.annotations().value(BANDWIDTH);
            if (existingBwAnnotation != null) {
                existingBwValue = Bandwidth.bps(Double.parseDouble(existingBwAnnotation));

                /*
                 * The computation is a shared bandwidth constraint based, so need to remove bandwidth constraint which
                 * has been utilized to create shared bandwidth constraint.
                 */
                if (bwConstraint != null) {
                    constraints.remove(bwConstraint);
                }
            }

            if (existingBwValue != null) {
                if (bwConstraint == null) {
                    bwConstraintValue = existingBwValue.bps();
                }
                //If bandwidth constraints not specified , take existing bandwidth for shared bandwidth calculation
                shBwConstraint = bwConstraint != null ? new SharedBandwidthConstraint(links,
                        existingBwValue, bwConstraint.bandwidth()) : new SharedBandwidthConstraint(links,
                        existingBwValue, existingBwValue);

                constraints.add(shBwConstraint);
            }
        } else {
            constraints = new LinkedList<>();
        }

        constraints.add(CapabilityConstraint.of(CapabilityType.valueOf(lspSigType)));
        if (costConstraint != null) {
            constraints.add(costConstraint);
        } else {
            //Take cost constraint from old tunnel if it is not specified in update flow
            costType = tunnel.annotations().value(COST_TYPE);
            costConstraint = CostConstraint.of(CostConstraint.Type.valueOf(costType));
            constraints.add(costConstraint);
        }

        List<ExplicitPathInfo> explicitPathInfo = pceStore
                .getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value());
        if (explicitPathInfo != null) {
            List<Path> finalComputedPath = computeExplicitPath(explicitPathInfo,
                    tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
                    constraints);

            if (finalComputedPath == null) {
                return false;
            }

            List<Link> totalLinks = new LinkedList<>();
            double totalCost = 0;
            //Add all partial computed paths
            for (Path path : finalComputedPath) {
                totalLinks.addAll(path.links());
                totalCost = totalCost + path.cost();
            }
            computedPathSet.add(new DefaultPath(finalComputedPath.iterator().next().providerId(),
                    totalLinks, totalCost));
        } else {
            computedPathSet = computePath(tunnel.path().src().deviceId(), tunnel.path().dst().deviceId(),
                    constraints);
        }

        // NO-PATH
        if (computedPathSet.isEmpty()) {
            return false;
        }

        Builder annotationBuilder = DefaultAnnotations.builder();
        annotationBuilder.set(BANDWIDTH, String.valueOf(bwConstraintValue));
        if (costType != null) {
            annotationBuilder.set(COST_TYPE, costType);
        }
        annotationBuilder.set(LSP_SIG_TYPE, lspSigType);
        annotationBuilder.set(PCE_INIT, TRUE);
        annotationBuilder.set(DELEGATE, TRUE);
        annotationBuilder.set(PLSP_ID, tunnel.annotations().value(PLSP_ID));
        annotationBuilder.set(PCC_TUNNEL_ID, tunnel.annotations().value(PCC_TUNNEL_ID));

        Path computedPath = computedPathSet.iterator().next();
        LspType lspType = LspType.valueOf(lspSigType);
        long localLspId = 0;
        if (lspType != WITH_SIGNALLING) {
            /*
             * Local LSP id which is assigned by RSVP for RSVP signalled LSPs, will be assigned by
             * PCE for non-RSVP signalled LSPs.
             */
            localLspId = getNextLocalLspId();
            annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(localLspId));
        }

        Tunnel updatedTunnel = new DefaultTunnel(null, tunnel.src(), tunnel.dst(), MPLS, INIT, null, null,
                                                 tunnel.tunnelName(), computedPath,
                                                 annotationBuilder.build());

        // Allocate shared bandwidth for all tunnels.
        if (bwConstraintValue != 0) {
            if (!reserveBandwidth(computedPath, bwConstraintValue, shBwConstraint)) {
                return false;
            }
        }

        TunnelId updatedTunnelId = tunnelService.setupTunnel(appId, links.get(0).src().deviceId(), updatedTunnel,
                                                             computedPath);

        if (updatedTunnelId == null) {
            if (bwConstraintValue != 0) {
                releaseSharedBwForNewTunnel(computedPath, bwConstraintValue, shBwConstraint);
            }
            return false;
        }

        if (bwConstraintValue != 0 && lspType == WITH_SIGNALLING) {
            rsvpTunnelsWithLocalBw.add(updatedTunnelId);
        }

        return true;
    }

    @Override
    public boolean releasePath(TunnelId tunnelId) {
        checkNotNull(tunnelId);
        // 1. Query Tunnel from Tunnel manager.
        Tunnel tunnel = tunnelService.queryTunnel(tunnelId);

        if (tunnel == null) {
            return false;
        }

        // 2. Call tunnel service.
        return tunnelService.downTunnel(appId, tunnel.tunnelId());
    }

    @Override
    public boolean releasePath(String loadBalancingPathName) {
        checkNotNull(loadBalancingPathName);

        List<TunnelId> tunnelIds = pceStore.getLoadBalancingTunnelIds(loadBalancingPathName);
        if (tunnelIds != null && !tunnelIds.isEmpty()) {
            for (TunnelId id : tunnelIds) {
                if (!tunnelService.downTunnel(appId, id)) {
                    return false;
                }
            }

            //pceStore.removeDisjointPathInfo(loadBalancedPathName);
            pceStore.removeLoadBalancingTunnelIdsInfo(loadBalancingPathName);
            return true;
        }

        return false;
    }

    @Override
    public Iterable<Tunnel> queryAllPath() {
        return tunnelService.queryTunnel(MPLS);
    }

    @Override
    public Tunnel queryPath(TunnelId tunnelId) {
        return tunnelService.queryTunnel(tunnelId);
    }

    private boolean releaseSharedBwForNewTunnel(Path computedPath, double bandwidthConstraint,
                                                SharedBandwidthConstraint shBwConstraint) {
        checkNotNull(computedPath);
        checkNotNull(bandwidthConstraint);
        double bwToAllocate;

        Double additionalBwValue = null;
        if (shBwConstraint != null) {
            additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
                    : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
        }

        for (Link link : computedPath.links()) {
            bwToAllocate = 0;
            if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
                if (additionalBwValue != null) {
                    bwToAllocate = additionalBwValue;
                }
            } else {
                bwToAllocate = bandwidthConstraint;
            }

            if (bwToAllocate != 0) {
                bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link), bwToAllocate);
            }
        }
        return true;
    }

    /**
     * Returns the next local LSP identifier to be used either by getting from
     * freed list if available otherwise generating a new one.
     *
     * @return value of local LSP identifier
     */
    private synchronized short getNextLocalLspId() {
        // If there is any free id use it. Otherwise generate new id.
        if (localLspIdFreeList.isEmpty()) {
            return (short) localLspIdIdGen.getNewId();
        }
        Iterator<Short> it = localLspIdFreeList.iterator();
        Short value = it.next();
        localLspIdFreeList.remove(value);
        return value;
    }

    protected class TeConstraintBasedLinkWeight implements LinkWeight {

        private final List<Constraint> constraints;

        /**
         * Creates a new edge-weight function capable of evaluating links
         * on the basis of the specified constraints.
         *
         * @param constraints path constraints
         */
        public TeConstraintBasedLinkWeight(List<Constraint> constraints) {
            if (constraints == null) {
                this.constraints = Collections.emptyList();
            } else {
                this.constraints = ImmutableList.copyOf(constraints);
            }
        }

        @Override
        public double weight(TopologyEdge edge) {
            if (!constraints.iterator().hasNext()) {
                //Takes default cost/hopcount as 1 if no constraints specified
                return 1.0;
            }

            Iterator<Constraint> it = constraints.iterator();
            double cost = 1;

            //If any constraint fails return -1 also value of cost returned from cost constraint can't be negative
            while (it.hasNext() && cost > 0) {
                Constraint constraint = it.next();
                if (constraint instanceof CapabilityConstraint) {
                    cost = ((CapabilityConstraint) constraint).isValidLink(edge.link(), deviceService,
                                                                           netCfgService) ? 1 : -1;
                } else if (constraint instanceof PceBandwidthConstraint) {
                    cost = ((PceBandwidthConstraint) constraint).isValidLink(edge.link(),
                            bandwidthMgmtService) ? 1 : -1;
                } else if (constraint instanceof SharedBandwidthConstraint) {
                    cost = ((SharedBandwidthConstraint) constraint).isValidLink(edge.link(),
                            bandwidthMgmtService) ? 1 : -1;
                } else if (constraint instanceof CostConstraint) {
                    cost = ((CostConstraint) constraint).isValidLink(edge.link(), netCfgService);
                } else {
                    cost = constraint.cost(edge.link(), null);
                }
            }
            return cost;
        }
    }

    //TODO: annotations used for temporarily later projection/network config will be used
    private class InternalTopologyListener implements TopologyListener {
       @Override
        public void event(TopologyEvent event) {
             event.reasons().forEach(e -> {
                //If event type is link removed, get the impacted tunnel
                if (e instanceof LinkEvent) {
                    LinkEvent linkEvent = (LinkEvent) e;
                    if (linkEvent.type() == LinkEvent.Type.LINK_REMOVED) {
                        tunnelService.queryTunnel(MPLS).forEach(t -> {
                                if (t.path().links().contains((e.subject()))) {
                                    // Check whether this ONOS instance is master for ingress device if yes,
                                    // recompute and send update
                                    checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
                                }
                        });
                    }
                }
                });
        }
    }

    private boolean checkForMasterAndUpdateTunnel(DeviceId src, Tunnel tunnel) {
        /**
         * Master of ingress node will recompute and also delegation flag must be set.
         */
        if (mastershipService.isLocalMaster(src)
                && Boolean.valueOf(tunnel.annotations().value(DELEGATE)) != null) {
            LinkedList<Constraint> constraintList = new LinkedList<>();

            if (tunnel.annotations().value(BANDWIDTH) != null) {
                //Requested bandwidth will be same as previous allocated bandwidth for the tunnel
                PceBandwidthConstraint localConst = new PceBandwidthConstraint(Bandwidth.bps(Double.parseDouble(tunnel
                        .annotations().value(BANDWIDTH))));
                constraintList.add(localConst);
            }
            if (tunnel.annotations().value(COST_TYPE) != null) {
                constraintList.add(CostConstraint.of(CostConstraint.Type.valueOf(tunnel.annotations().value(
                        COST_TYPE))));
            }

            /*
             * If tunnel was UP after recomputation failed then store failed path in PCE store send PCIntiate(remove)
             * and If tunnel is failed and computation fails nothing to do because tunnel status will be same[Failed]
             */
            if (!updatePath(tunnel.tunnelId(), constraintList) && !tunnel.state().equals(Tunnel.State.FAILED)) {
                // If updation fails store in PCE store as failed path
                // then PCInitiate (Remove)
                pceStore.addFailedPathInfo(new PcePathInfo(tunnel.path().src().deviceId(), tunnel
                        .path().dst().deviceId(), tunnel.tunnelName().value(), constraintList,
                        LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)),
                         pceStore.getTunnelNameExplicitPathInfoMap(tunnel.tunnelName().value()),
                        tunnel.annotations().value(LOAD_BALANCING_PATH_NAME) != null ? true : false));
                //Release that tunnel calling PCInitiate
                releasePath(tunnel.tunnelId());
            }
        }

        return false;
    }

     // Allocates the bandwidth locally for PCECC tunnels.
    private boolean reserveBandwidth(Path computedPath, double bandwidthConstraint,
                                  SharedBandwidthConstraint shBwConstraint) {
        checkNotNull(computedPath);
        checkNotNull(bandwidthConstraint);
        Resource resource = null;
        double bwToAllocate = 0;
        Map<Link, Double> linkMap = new HashMap<>();

        /**
         * Shared bandwidth sub-case : Lesser bandwidth required than original -
         * No reservation required.
         */
        Double additionalBwValue = null;
        if (shBwConstraint != null) {
            additionalBwValue = ((bandwidthConstraint - shBwConstraint.sharedBwValue().bps()) <= 0) ? null
                : (bandwidthConstraint - shBwConstraint.sharedBwValue().bps());
        }

        Optional<ResourceAllocation> resAlloc = null;
        for (Link link : computedPath.links()) {
            bwToAllocate = 0;
            if ((shBwConstraint != null) && (shBwConstraint.links().contains(link))) {
                if (additionalBwValue != null) {
                    bwToAllocate = additionalBwValue;
                }
            } else {
                bwToAllocate = bandwidthConstraint;
            }

            /**
             *  In shared bandwidth cases, where new BW is lesser than old BW, it
             *  is not required to allocate anything.
             */
            if (bwToAllocate != 0) {
                if (!bandwidthMgmtService.allocLocalReservedBw(LinkKey.linkKey(link.src(), link.dst()),
                        bwToAllocate)) {
                    // If allocation for any link fails, then release the partially allocated bandwidth
                    // for all links allocated
                    linkMap.forEach((ln, aDouble) -> bandwidthMgmtService
                                                     .releaseLocalReservedBw(LinkKey.linkKey(ln), aDouble));
                    return false;
                }

                linkMap.put(link, bwToAllocate);
            }
        }

        return true;
    }

    /*
     * Deallocates the bandwidth which is reserved locally for PCECC tunnels.
     */
    private void releaseBandwidth(Tunnel tunnel) {
        // Between same source and destination, search the tunnel with same symbolic path name.
        Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
        Tunnel newTunnel = null;
        for (Tunnel tunnelObj : tunnelQueryResult) {
            if (tunnel.tunnelName().value().equals(tunnelObj.tunnelName().value())) {
                newTunnel = tunnelObj;
                break;
            }
        }

        // Even if one link is shared, the bandwidth release should happen based on shared mechanism.
        boolean isLinkShared = false;
        if (newTunnel != null) {
            for (Link link : tunnel.path().links()) {
                if (newTunnel.path().links().contains(link)) {
                    isLinkShared = true;
                    break;
                }
            }
        }

        if (isLinkShared) {
            releaseSharedBandwidth(newTunnel, tunnel);
            return;
        }

        tunnel.path().links().forEach(tn -> bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(tn),
                Double.parseDouble(tunnel.annotations().value(BANDWIDTH))));
    }

    /**
     *  Re-allocates the bandwidth for the tunnel for which the bandwidth was
     *  allocated in shared mode initially.
     */
    private synchronized void releaseSharedBandwidth(Tunnel newTunnel, Tunnel oldTunnel) {

        boolean isAllocate = false;
        Double oldTunnelBw = Double.parseDouble(oldTunnel.annotations().value(BANDWIDTH));
        Double newTunnelBw = Double.parseDouble(newTunnel.annotations().value(BANDWIDTH));

        if (newTunnelBw > oldTunnelBw) {
            isAllocate = true;
        }

        for (Link link : newTunnel.path().links()) {
            if (oldTunnel.path().links().contains(link)) {
                if (!isAllocate) {
                    bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link),
                            oldTunnelBw - newTunnelBw);
                }
            } else {
                bandwidthMgmtService.releaseLocalReservedBw(LinkKey.linkKey(link), oldTunnelBw);
            }
        }
    }

    // Listens on tunnel events.
    private class InnerTunnelListener implements TunnelListener {
        @Override
        public void event(TunnelEvent event) {
            // Event gets generated with old tunnel object.
            Tunnel tunnel = event.subject();
            if (tunnel.type() != MPLS) {
                return;
            }

            LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));
            String tunnelBandwidth = tunnel.annotations().value(BANDWIDTH);
            double bwConstraintValue = 0;
            if (tunnelBandwidth != null) {
                bwConstraintValue = Double.parseDouble(tunnelBandwidth);
            }

            switch (event.type()) {
            case TUNNEL_UPDATED:
                if (rsvpTunnelsWithLocalBw.contains(tunnel.tunnelId())) {
                    releaseBandwidth(event.subject());
                        rsvpTunnelsWithLocalBw.remove(tunnel.tunnelId());
                }

                if (tunnel.state() == UNSTABLE) {
                    /*
                     * During LSP DB sync if PCC doesn't report LSP which was PCE initiated, it's state is turned into
                     * unstable so that it can be setup again. Add into failed path store so that it can be recomputed
                     * and setup while global reoptimization.
                     */

                    List<Constraint> constraints = new LinkedList<>();
                    String bandwidth = tunnel.annotations().value(BANDWIDTH);
                    if (bandwidth != null) {
                        constraints.add(new PceBandwidthConstraint(Bandwidth
                                .bps(Double.parseDouble(bandwidth))));
                    }

                    String costType = tunnel.annotations().value(COST_TYPE);
                    if (costType != null) {
                        CostConstraint costConstraint = new CostConstraint(CostConstraint.Type.valueOf(costType));
                        constraints.add(costConstraint);
                    }

                    constraints.add(CapabilityConstraint
                            .of(CapabilityType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))));

                    List<Link> links = tunnel.path().links();
                    pceStore.addFailedPathInfo(new PcePathInfo(links.get(0).src().deviceId(),
                                                                  links.get(links.size() - 1).dst().deviceId(),
                                                                  tunnel.tunnelName().value(), constraints, lspType,
                                                                  pceStore.getTunnelNameExplicitPathInfoMap(tunnel
                                                                          .tunnelName().value()), tunnel.annotations()
                            .value(LOAD_BALANCING_PATH_NAME) != null ? true : false));
                }

                break;

            case TUNNEL_REMOVED:
                if (lspType != WITH_SIGNALLING) {
                    localLspIdFreeList.add(Short.valueOf(tunnel.annotations().value(LOCAL_LSP_ID)));
                }
                // If not zero bandwidth, and delegated (initiated LSPs will also be delegated).
                if (bwConstraintValue != 0 && mastershipService.getLocalRole(tunnel.path().src()
                        .deviceId()) == MastershipRole.MASTER) {
                    if (lspType != WITH_SIGNALLING) {
                        releaseBandwidth(tunnel);
                    }
                }

                /*if (pceStore.getTunnelInfo(tunnel.tunnelId()) != null) {
                    pceStore.removeTunnelInfo(tunnel.tunnelId());
                }*/

                break;

            default:
                break;

            }
            return;
        }
    }

    @Override
    public List<ExplicitPathInfo> explicitPathInfoList(String tunnelName) {
        return pceStore.getTunnelNameExplicitPathInfoMap(tunnelName);
    }

    @Override
    public List<TunnelId> queryLoadBalancingPath(String pathName) {
        return pceStore.getLoadBalancingTunnelIds(pathName);
    }

    //Computes path from tunnel store and also path failed to setup.
    private void callForOptimization() {
        //Recompute the LSPs which it was delegated [LSPs stored in PCE store (failed paths)]
        for (PcePathInfo failedPathInfo : pceStore.getFailedPathInfos()) {
            checkForMasterAndSetupPath(failedPathInfo);
        }

        //Recompute the LSPs for which it was delegated [LSPs stored in tunnel store]
        tunnelService.queryTunnel(MPLS).forEach(t -> {
        checkForMasterAndUpdateTunnel(t.path().src().deviceId(), t);
        });
    }

    private boolean checkForMasterAndSetupPath(PcePathInfo failedPathInfo) {
        /**
         * Master of ingress node will setup the path failed stored in PCE store.
         */
        if (mastershipService.isLocalMaster(failedPathInfo.src())) {
            if (setupPath(failedPathInfo.src(), failedPathInfo.dst(), failedPathInfo.name(),
                    failedPathInfo.constraints(), failedPathInfo.lspType(), failedPathInfo.explicitPathInfo())) {
                // If computation is success remove that path
                pceStore.removeFailedPathInfo(failedPathInfo);
                return true;
            }
        }

        return false;
    }

    //Timer to call global optimization
    private class GlobalOptimizationTimer implements Runnable {

        public GlobalOptimizationTimer() {
        }

        @Override
        public void run() {
            callForOptimization();
        }
    }
}
