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

import com.google.common.collect.Maps;
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.Property;
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.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.DefaultGroupId;
import org.onosproject.incubator.net.tunnel.DefaultOpticalTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.DefaultTunnel;
import org.onosproject.incubator.net.tunnel.DefaultTunnelDescription;
import org.onosproject.incubator.net.tunnel.DefaultTunnelStatistics;
import org.onosproject.incubator.net.tunnel.IpTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.OpticalLogicId;
import org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint;
import org.onosproject.incubator.net.tunnel.Tunnel;
import org.onosproject.incubator.net.tunnel.TunnelDescription;
import org.onosproject.incubator.net.tunnel.TunnelEndPoint;
import org.onosproject.incubator.net.tunnel.TunnelId;
import org.onosproject.incubator.net.tunnel.TunnelName;
import org.onosproject.incubator.net.tunnel.TunnelProvider;
import org.onosproject.incubator.net.tunnel.TunnelProviderRegistry;
import org.onosproject.incubator.net.tunnel.TunnelProviderService;
import org.onosproject.incubator.net.tunnel.TunnelService;
import org.onosproject.incubator.net.tunnel.TunnelStatistics;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.IpElementId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.provider.AbstractProvider;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pcep.api.PcepController;
import org.onosproject.pcep.api.PcepDpid;
import org.onosproject.pcep.api.PcepHopNodeDescription;
import org.onosproject.pcep.api.PcepOperator.OperationType;
import org.onosproject.pcep.api.PcepTunnel;
import org.onosproject.pcep.api.PcepTunnel.PathState;
import org.onosproject.pcep.api.PcepTunnel.PathType;
import org.onosproject.pcep.api.PcepTunnelListener;
import org.onosproject.pcep.api.PcepTunnelStatistics;
import org.onosproject.pcep.controller.PccId;
import org.onosproject.pcep.controller.PcepClient;
import org.onosproject.pcep.controller.PcepClientController;
import org.onosproject.pcep.controller.PcepClientListener;
import org.onosproject.pcep.controller.PcepEventListener;
import org.onosproject.pcepio.exceptions.PcepParseException;
import org.onosproject.pcepio.protocol.PcInitiatedLspRequest;
import org.onosproject.pcepio.protocol.PcepAttribute;
import org.onosproject.pcepio.protocol.PcepBandwidthObject;
import org.onosproject.pcepio.protocol.PcepEndPointsObject;
import org.onosproject.pcepio.protocol.PcepEroObject;
import org.onosproject.pcepio.protocol.PcepInitiateMsg;
import org.onosproject.pcepio.protocol.PcepLspObject;
import org.onosproject.pcepio.protocol.PcepMessage;
import org.onosproject.pcepio.protocol.PcepMsgPath;
import org.onosproject.pcepio.protocol.PcepReportMsg;
import org.onosproject.pcepio.protocol.PcepRroObject;
import org.onosproject.pcepio.protocol.PcepSrpObject;
import org.onosproject.pcepio.protocol.PcepStateReport;
import org.onosproject.pcepio.protocol.PcepUpdateMsg;
import org.onosproject.pcepio.protocol.PcepUpdateRequest;
import org.onosproject.pcepio.types.IPv4SubObject;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.StatefulIPv4LspIdentidiersTlv;
import org.onosproject.pcepio.types.SymbolicPathNameTlv;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Modified;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;
import java.util.Optional;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.util.Tools.get;
import static org.onosproject.net.DefaultAnnotations.EMPTY;
import static org.onosproject.net.DeviceId.deviceId;
import static org.onosproject.net.PortNumber.portNumber;
import static org.onosproject.pcep.api.PcepDpid.uri;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider which uses an PCEP controller to detect, update, create network
 * tunnels.
 */
@Component(immediate = true)
@Service
public class PcepTunnelProvider extends AbstractProvider implements TunnelProvider {

    private static final Logger log = getLogger(PcepTunnelProvider.class);
    private static final long MAX_BANDWIDTH = 99999744;
    private static final long MIN_BANDWIDTH = 64;
    private static final String BANDWIDTH_UINT = "kbps";
    static final String PROVIDER_ID = "org.onosproject.provider.tunnel.pcep";

    static final int POLL_INTERVAL = 10;
    @Property(name = "tunnelStatsPollFrequency", intValue = POLL_INTERVAL,
            label = "Frequency (in seconds) for polling tunnel statistics")
    private int tunnelStatsPollFrequency = POLL_INTERVAL;

    private static final String TUNNLE_NOT_NULL = "Create failed,The given port may be wrong or has been occupied.";

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected TunnelProviderRegistry tunnelProviderRegistry;

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    protected PcepClientController pcepClientController;

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

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

    TunnelProviderService service;

    HashMap<String, TunnelId> tunnelMap = new HashMap<String, TunnelId>();
    HashMap<TunnelId, TunnelStatistics> tunnelStatisticsMap = new HashMap<>();
    private HashMap<Long, TunnelStatsCollector> collectors = Maps.newHashMap();

    private InnerTunnelProvider listener = new InnerTunnelProvider();

    protected PcepTunnelApiMapper pcepTunnelApiMapper = new PcepTunnelApiMapper();
    private static final int DEFAULT_BANDWIDTH_VALUE = 10;

    /**
     * Creates a Tunnel provider.
     */
    public PcepTunnelProvider() {
        super(new ProviderId("pcep", PROVIDER_ID));
    }

    @Activate
    public void activate() {
        cfgService.registerProperties(getClass());
        service = tunnelProviderRegistry.register(this);
        controller.addTunnelListener(listener);
        pcepClientController.addListener(listener);
        pcepClientController.addEventListener(listener);
        tunnelService.queryAllTunnels().forEach(tunnel -> {
            String pcepTunnelId = getPcepTunnelKey(tunnel.tunnelId());
            TunnelStatsCollector tsc = new TunnelStatsCollector(pcepTunnelId, tunnelStatsPollFrequency);
            tsc.start();
            collectors.put(tunnel.tunnelId().id(), tsc);

        });

        log.info("Started");
    }

    @Deactivate
    public void deactivate() {
        tunnelProviderRegistry.unregister(this);
        controller.removeTunnelListener(listener);
        collectors.values().forEach(TunnelStatsCollector::stop);
        pcepClientController.removeListener(listener);
        log.info("Stopped");
    }

    @Modified
    public void modified(ComponentContext context) {
        Dictionary<?, ?> properties = context.getProperties();
        int newTunnelStatsPollFrequency;
        try {
            String s = get(properties, "tunnelStatsPollFrequency");
            newTunnelStatsPollFrequency = isNullOrEmpty(s) ? tunnelStatsPollFrequency : Integer.parseInt(s.trim());

        } catch (NumberFormatException | ClassCastException e) {
            newTunnelStatsPollFrequency = tunnelStatsPollFrequency;
        }

        if (newTunnelStatsPollFrequency != tunnelStatsPollFrequency) {
            tunnelStatsPollFrequency = newTunnelStatsPollFrequency;
            collectors.values().forEach(tsc -> tsc.adjustPollInterval(tunnelStatsPollFrequency));
            log.info("New setting: tunnelStatsPollFrequency={}", tunnelStatsPollFrequency);
        }

    }

    @Override
    public void setupTunnel(Tunnel tunnel, Path path) {
        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        // Get the pcc client
        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                              + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
            return;
        }

        //If stateful and PC Initiation capability is not supported by client not sending Initiate msg
        if (pc.capability().pcInstantiationCapability()) {
            pcepSetupTunnel(tunnel, path, pc);
        }
    }

    @Override
    public void setupTunnel(ElementId srcElement, Tunnel tunnel, Path path) {

        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        if (!(srcElement instanceof IpElementId)) {
            log.error("Element id is not valid");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpElementId) srcElement).ipAddress().toString());
            return;
        }

        if (pc.capability().pcInstantiationCapability()) {
            pcepSetupTunnel(tunnel, path, pc);
        }
    }

    @Override
    public void releaseTunnel(Tunnel tunnel) {

        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
            return;
        }

        if (pc.capability().pcInstantiationCapability()) {
            pcepReleaseTunnel(tunnel, pc);
        }
    }

    @Override
    public void releaseTunnel(ElementId srcElement, Tunnel tunnel) {
        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        if (!(srcElement instanceof IpElementId)) {
            log.error("Element id is not valid");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpElementId) srcElement).ipAddress().toString());
            return;
        }

        if (pc.capability().pcInstantiationCapability()) {
            pcepReleaseTunnel(tunnel, pc);
        }
    }

    @Override
    public void updateTunnel(Tunnel tunnel, Path path) {
        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpTunnelEndPoint) tunnel.src()).ip()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
            return;
        }

        if (pc.capability().statefulPceCapability()) {
            pcepUpdateTunnel(tunnel, path, pc);
        }
    }

    @Override
    public void updateTunnel(ElementId srcElement, Tunnel tunnel, Path path) {

        if (tunnel.type() != Tunnel.Type.MPLS) {
            log.error("Tunnel Type MPLS is only supported");
            return;
        }

        if (!(srcElement instanceof IpElementId)) {
            log.error("Element id is not valid");
            return;
        }

        // check for tunnel end points
        if (!(tunnel.src() instanceof IpTunnelEndPoint) || !(tunnel.dst() instanceof IpTunnelEndPoint)) {
            log.error("Tunnel source or destination is not valid");
            return;
        }

        PcepClient pc = pcepClientController.getClient(PccId.pccId(((IpElementId) srcElement).ipAddress()));

        if (!(pc instanceof PcepClient)) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpElementId) srcElement).ipAddress().toString());
            return;
        }

        if (pc.capability().statefulPceCapability()) {
            pcepUpdateTunnel(tunnel, path, pc);
        }
    }

    @Override
    public TunnelId tunnelAdded(TunnelDescription tunnel) {
        if (tunnel.type() == Tunnel.Type.MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
            return service.tunnelAdded(tunnel);
        }

        long bandwidth = Long
                .parseLong(tunnel.annotations().value("bandwidth"));

        if (bandwidth < MIN_BANDWIDTH || bandwidth > MAX_BANDWIDTH) {
            error("Update failed, invalid bandwidth.");
            return null;
        }

        // endpoints
        OpticalTunnelEndPoint src = (org.onosproject.incubator.net.tunnel.OpticalTunnelEndPoint) tunnel
                .src();
        OpticalTunnelEndPoint dst = (OpticalTunnelEndPoint) tunnel.dst();
        // devices
        DeviceId srcId = (DeviceId) src.elementId().get();
        DeviceId dstId = (DeviceId) dst.elementId().get();

        // ports
        long srcPort = src.portNumber().get().toLong();
        long dstPort = dst.portNumber().get().toLong();

        // type
        if (tunnel.type() != Tunnel.Type.VLAN) {
            error("Illegal tunnel type. Only support VLAN tunnel creation.");
            return null;
        }

        PcepTunnel pcepTunnel = controller.applyTunnel(srcId, dstId, srcPort,
                                                       dstPort, bandwidth,
                                                       tunnel.tunnelName()
                                                       .value());

        checkNotNull(pcepTunnel, TUNNLE_NOT_NULL);
        TunnelDescription tunnelAdded = buildOpticalTunnel(pcepTunnel, null);
        TunnelId tunnelId = service.tunnelAdded(tunnelAdded);

        tunnelMap.put(String.valueOf(pcepTunnel.id()), tunnelId);
        return tunnelId;
    }

    @Override
    public void tunnelRemoved(TunnelDescription tunnel) {
        if (tunnel.type() == Tunnel.Type.MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
            service.tunnelRemoved(tunnel);
        }

        Tunnel tunnelOld = tunnelQueryById(tunnel.id());
        checkNotNull(tunnelOld, "The tunnel id is not exsited.");
        if (tunnelOld.type() != Tunnel.Type.VLAN) {
            error("Illegal tunnel type. Only support VLAN tunnel deletion.");
            return;
        }
        String pcepTunnelId = getPcepTunnelKey(tunnel.id());
        checkNotNull(pcepTunnelId, "The tunnel id is not exsited.");
        if (!controller.deleteTunnel(pcepTunnelId)) {
            error("Delete tunnel failed, Maybe some devices have been disconnected.");
            return;
        }
        tunnelMap.remove(pcepTunnelId);
        service.tunnelRemoved(tunnel);
    }

    @Override
    public void tunnelUpdated(TunnelDescription tunnel) {
        if (tunnel.type() == Tunnel.Type.MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.id());
            service.tunnelUpdated(tunnel);
        }

        Tunnel tunnelOld = tunnelQueryById(tunnel.id());
        if (tunnelOld.type() != Tunnel.Type.VLAN) {
            error("Illegal tunnel type. Only support VLAN tunnel update.");
            return;
        }
        long bandwidth = Long
                .parseLong(tunnel.annotations().value("bandwidth"));
        if (bandwidth < MIN_BANDWIDTH || bandwidth > MAX_BANDWIDTH) {
            error("Update failed, invalid bandwidth.");
            return;
        }
        String pcepTunnelId = getPcepTunnelKey(tunnel.id());

        checkNotNull(pcepTunnelId, "Invalid tunnel id");
        if (!controller.updateTunnelBandwidth(pcepTunnelId, bandwidth)) {

            error("Update failed,maybe invalid bandwidth.");
            return;

        }
        service.tunnelUpdated(tunnel);
    }

    private void error(String info) {
        System.err.println(info);
    }

    // Short-hand for creating a connection point.
    private ConnectPoint connectPoint(PcepDpid id, long port) {
        return new ConnectPoint(deviceId(uri(id)), portNumber(port));
    }

    // Short-hand for creating a link.
    private Link link(PcepDpid src, long sp, PcepDpid dst, long dp) {
        return DefaultLink.builder()
                .providerId(id())
                .src(connectPoint(src, sp))
                .dst(connectPoint(dst, dp))
                .type(Link.Type.TUNNEL)
                .build();
    }

    // Creates a path that leads through the given devices.
    private Path createPath(List<PcepHopNodeDescription> hopList,
                            PathType pathtype, PathState pathState) {
        if (hopList == null || hopList.size() == 0) {
            return null;
        }
        List<Link> links = new ArrayList<>();
        for (int i = 1; i < hopList.size() - 1; i = i + 2) {
            links.add(link(hopList.get(i).getDeviceId(), hopList.get(i)
                    .getPortNum(), hopList.get(i + 1).getDeviceId(), hopList
                    .get(i + 1).getPortNum()));
        }

        int hopNum = hopList.size() - 2;
        DefaultAnnotations extendAnnotations = DefaultAnnotations.builder()
                .set("pathNum", String.valueOf(hopNum))
                .set("pathState", String.valueOf(pathState))
                .set("pathType", String.valueOf(pathtype)).build();
        return new DefaultPath(id(), links, hopNum, extendAnnotations);
    }

    // convert the path description to a string.
    public String pathToString(List<Link> links) {
        StringBuilder builder = new StringBuilder();
        builder.append("{");
        for (Link link : links) {
            builder.append("(Device:" + link.src().deviceId() + "  Port:"
                    + link.src().port().toLong());
            builder.append(" Device:" + link.dst().deviceId() + "  Port:"
                    + link.dst().port().toLong());
            builder.append(")");
        }
        builder.append("}");
        return builder.toString();
    }

    // build a TunnelDescription.
    private TunnelDescription buildOpticalTunnel(PcepTunnel pcepTunnel,
                                                 TunnelId tunnelId) {
        TunnelEndPoint srcPoint = null;
        TunnelEndPoint dstPoint = null;
        Tunnel.Type tunnelType = null;
        TunnelName name = TunnelName.tunnelName(pcepTunnel.name());

        // add path after codes of tunnel's path merged
        Path path = createPath(pcepTunnel.getHopList(),
                               pcepTunnel.getPathType(),
                               pcepTunnel.getPathState());

        OpticalTunnelEndPoint.Type endPointType = null;
        switch (pcepTunnel.type()) {
        case OCH:
            tunnelType = Tunnel.Type.OCH;
            endPointType = OpticalTunnelEndPoint.Type.LAMBDA;
            break;

        case OTN:
            tunnelType = Tunnel.Type.ODUK;
            endPointType = OpticalTunnelEndPoint.Type.TIMESLOT;
            break;

        case UNI:
            tunnelType = Tunnel.Type.VLAN;
            endPointType = null;
            break;

        default:
            break;
        }
        DeviceId srcDid = deviceId(uri(pcepTunnel.srcDeviceID()));
        DeviceId dstDid = deviceId(uri(pcepTunnel.dstDeviceId()));
        PortNumber srcPort = PortNumber.portNumber(pcepTunnel.srcPort());
        PortNumber dstPort = PortNumber.portNumber(pcepTunnel.dstPort());

        srcPoint = new DefaultOpticalTunnelEndPoint(id(), Optional.of(srcDid),
                                                    Optional.of(srcPort), null,
                                                    endPointType,
                                                    OpticalLogicId.logicId(0),
                                                    true);
        dstPoint = new DefaultOpticalTunnelEndPoint(id(), Optional.of(dstDid),
                                                    Optional.of(dstPort), null,
                                                    endPointType,
                                                    OpticalLogicId.logicId(0),
                                                    true);

        // basic annotations
        DefaultAnnotations annotations = DefaultAnnotations
                .builder()
                .set("SLA", String.valueOf(pcepTunnel.getSla()))
                .set("bandwidth",
                     String.valueOf(pcepTunnel.bandWidth()) + BANDWIDTH_UINT)
                .set("index", String.valueOf(pcepTunnel.id())).build();

        // a VLAN tunnel always carry OCH tunnel, this annotation is the index
        // of a OCH tunnel.
        if (pcepTunnel.underlayTunnelId() != 0) {
            DefaultAnnotations extendAnnotations = DefaultAnnotations
                    .builder()
                    .set("underLayTunnelIndex",
                         String.valueOf(pcepTunnel.underlayTunnelId())).build();
            annotations = DefaultAnnotations.merge(annotations,
                                                   extendAnnotations);

        }
        TunnelDescription tunnel = new DefaultTunnelDescription(
                                                                tunnelId,
                                                                srcPoint,
                                                                dstPoint,
                                                                tunnelType,
                                                                new DefaultGroupId(
                                                                                   0),
                                                                id(), name,
                                                                path,
                                                                annotations);
        return tunnel;

    }

    /**
     * Get the tunnelID according to the tunnel key.
     *
     * @param tunnelKey tunnel key
     * @return corresponding tunnel id of the a tunnel key.
     */
    private TunnelId getTunnelId(String tunnelKey) {
        for (String key : tunnelMap.keySet()) {
            if (key.equals(tunnelKey)) {
                return tunnelMap.get(key);
            }
        }
        return null;
    }

    /**
     * Get the tunnel key according to the tunnelID.
     *
     * @param tunnelId tunnel id
     * @return corresponding a tunnel key of the tunnel id.
     */
    private String getPcepTunnelKey(TunnelId tunnelId) {
        for (String key : tunnelMap.keySet()) {
            if (tunnelMap.get(key).id() == tunnelId.id()) {
                return key;
            }
        }
        return null;

    }

    /**
     * Build a DefaultTunnelStatistics from a PcepTunnelStatistics.
     *
     * @param statistics statistics data from a PCEP tunnel
     * @return TunnelStatistics
     */
    private TunnelStatistics buildTunnelStatistics(PcepTunnelStatistics statistics) {
        DefaultTunnelStatistics.Builder builder = new DefaultTunnelStatistics.Builder();
        DefaultTunnelStatistics tunnelStatistics =  builder.setBwUtilization(statistics.bandwidthUtilization())
                    .setPacketLossRatio(statistics.packetLossRate())
                    .setFlowDelay(statistics.flowDelay())
                    .setAlarms(statistics.alarms())
                .build();
        return tunnelStatistics;
   }
    /**
     * Creates list of hops for ERO object from Path.
     *
     * @param path network path
     * @return list of ipv4 subobjects
     */
    private LinkedList<PcepValueType> createPcepPath(Path path) {
        LinkedList<PcepValueType> llSubObjects = new LinkedList<PcepValueType>();
        List<Link> listLink = path.links();
        ConnectPoint source = null;
        ConnectPoint destination = null;
        IpAddress ipDstAddress = null;
        IpAddress ipSrcAddress = null;
        PcepValueType subObj = null;

        for (Link link : listLink) {
            source = link.src();
            if (!(source.equals(destination))) {
                //set IPv4SubObject for ERO object
                ipSrcAddress = source.ipElementId().ipAddress();
                subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
                llSubObjects.add(subObj);
            }

            destination = link.dst();
            ipDstAddress = destination.ipElementId().ipAddress();
            subObj = new IPv4SubObject(ipDstAddress.getIp4Address().toInt());
            llSubObjects.add(subObj);
        }
        return llSubObjects;
    }

    /**
     * Creates PcInitiated lsp request list for setup tunnel.
     *
     * @param tunnel mpls tunnel
     * @param path network path
     * @param pc pcep client
     * @param srpId unique id for pcep message
     * @return list of PcInitiatedLspRequest
     * @throws PcepParseException while building pcep objects fails
     */
    LinkedList<PcInitiatedLspRequest> createPcInitiatedLspReqList(Tunnel tunnel, Path path,
                                                                  PcepClient pc, int srpId)
                                                                          throws PcepParseException {
        PcepValueType tlv;
        LinkedList<PcepValueType> llSubObjects = createPcepPath(path);

        if (llSubObjects == null || llSubObjects.size() == 0) {
            log.error("There is no link information to create tunnel");
            return null;
        }

        //build SRP object
        PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false).build();

        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
        LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();
        // set LSP identifiers TLV
        tlv = new StatefulIPv4LspIdentidiersTlv((((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
                                                (short) 0, (short) 0, 0,
                                                (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
        llOptionalTlv.add(tlv);
        //set SymbolicPathNameTlv of LSP object
        tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
        llOptionalTlv.add(tlv);

        //build LSP object
        PcepLspObject lspobj = pc.factory().buildLspObject().setAFlag(true).setOFlag((byte) 0).setPlspId(0)
                .setOptionalTlv(llOptionalTlv).build();

        //build ENDPOINTS object
        PcepEndPointsObject endpointsobj = pc.factory().buildEndPointsObject()
                .setSourceIpAddress(((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt())
                .setDestIpAddress(((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt())
                .setPFlag(true).build();

        //build ERO object
        PcepEroObject eroobj = pc.factory().buildEroObject().setSubObjects(llSubObjects).build();

        int iBandwidth = DEFAULT_BANDWIDTH_VALUE;
        if (tunnel.annotations().value("bandwidth") != null) {
            iBandwidth = Integer.parseInt(tunnel.annotations().value("bandwidth"));
        }
        // build bandwidth object
        PcepBandwidthObject bandwidthObject = pc.factory().buildBandwidthObject().setBandwidth(iBandwidth).build();
        // build pcep attribute
        PcepAttribute pcepAttribute = pc.factory().buildPcepAttribute().setBandwidthObject(bandwidthObject).build();

        PcInitiatedLspRequest initiateLspRequest = pc.factory().buildPcInitiatedLspRequest().setSrpObject(srpobj)
                .setLspObject(lspobj).setEndPointsObject(endpointsobj).setEroObject(eroobj)
                .setPcepAttribute(pcepAttribute).build();
        llPcInitiatedLspRequestList.add(initiateLspRequest);
        return llPcInitiatedLspRequestList;
    }

    /**
     * To send initiate tunnel message to pcc.
     *
     * @param tunnel mpls tunnel info
     * @param path explicit route for the tunnel
     * @param pc pcep client to send message
     */
    private void pcepSetupTunnel(Tunnel tunnel, Path path, PcepClient pc) {
        try {
            int srpId = SrpIdGenerators.create();
            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.CREATE);

            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);

            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = createPcInitiatedLspReqList(tunnel, path,
                                                                                                        pc, srpId);
            if (llPcInitiatedLspRequestList == null || llPcInitiatedLspRequestList.size() == 0) {
                log.error("Failed to create PcInitiatedLspRequestList");
                return;
            }

            //build PCInitiate message
            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList)
                    .build();

            pc.sendMessage(Collections.singletonList(pcInitiateMsg));

            pcepTunnelApiMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
        } catch (PcepParseException e) {
            log.error("PcepParseException occurred while processing setup tunnel {}", e.getMessage());
        }
    }

    /**
     * To send Release tunnel message to pcc.
     *
     * @param tunnel mpls tunnel info
     * @param pc pcep client to send message
     */
    private void pcepReleaseTunnel(Tunnel tunnel, PcepClient pc) {
        try {
            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, RequestType.DELETE);
            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
            int srpId = SrpIdGenerators.create();
            TunnelId tunnelId = tunnel.tunnelId();
            int plspId = 0;
            StatefulIPv4LspIdentidiersTlv statefulIpv4IndentifierTlv = null;

            if (!(pcepTunnelApiMapper.checkFromTunnelDBQueue(tunnelId))) {
                log.error("Tunnel doesnot exists. Tunnel id {}" + tunnelId.toString());
                return;
            } else {
                PcepTunnelData pcepTunnelDbData = pcepTunnelApiMapper.getDataFromTunnelDBQueue(tunnelId);
                plspId = pcepTunnelDbData.plspId();
                statefulIpv4IndentifierTlv = pcepTunnelDbData.statefulIpv4IndentifierTlv();
            }
            // build srp object
            PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(true).build();

            PcepValueType tlv;
            LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = new LinkedList<PcInitiatedLspRequest>();

            if (statefulIpv4IndentifierTlv != null) {
                tlv = statefulIpv4IndentifierTlv;
            } else {
                tlv = new StatefulIPv4LspIdentidiersTlv((
                        ((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
                        (short) 0, (short) 0, 0,
                        (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
            }
            llOptionalTlv.add(tlv);
            tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
            llOptionalTlv.add(tlv);
            // build lsp object, set r flag as false to delete the tunnel
            PcepLspObject lspobj = pc.factory().buildLspObject().setRFlag(false).setPlspId(plspId)
                    .setOptionalTlv(llOptionalTlv).build();

            PcInitiatedLspRequest releaseLspRequest = pc.factory().buildPcInitiatedLspRequest().setSrpObject(srpobj)
                    .setLspObject(lspobj).build();

            llPcInitiatedLspRequestList.add(releaseLspRequest);

            PcepInitiateMsg pcInitiateMsg = pc.factory().buildPcepInitiateMsg()
                    .setPcInitiatedLspRequestList(llPcInitiatedLspRequestList).build();

            pc.sendMessage(Collections.singletonList(pcInitiateMsg));

            pcepTunnelApiMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
        } catch (PcepParseException e) {
            log.error("PcepParseException occurred while processing release tunnel {}", e.getMessage());
        }
    }

    /**
     * To send Update tunnel request message to pcc.
     *
     * @param tunnel mpls tunnel info
     * @param path explicit route for the tunnel
     * @param pc pcep client to send message
     */
    private void pcepUpdateTunnel(Tunnel tunnel, Path path, PcepClient pc) {
        try {
            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.UPDATE);
            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
            int srpId = SrpIdGenerators.create();
            TunnelId tunnelId = tunnel.tunnelId();
            PcepValueType tlv;
            int plspId = 0;

            LinkedList<PcepValueType> llSubObjects = createPcepPath(path);
            LinkedList<PcepValueType> llOptionalTlv = new LinkedList<PcepValueType>();
            LinkedList<PcepUpdateRequest> llUpdateRequestList = new LinkedList<PcepUpdateRequest>();

            //build SRP object
            PcepSrpObject srpobj = pc.factory().buildSrpObject().setSrpID(srpId).setRFlag(false).build();

            if (!(pcepTunnelApiMapper.checkFromTunnelDBQueue(tunnelId))) {
                log.error("Tunnel doesnot exists in DB");
                return;
            } else {
                PcepTunnelData pcepTunnelDBData = pcepTunnelApiMapper.getDataFromTunnelDBQueue(tunnelId);
                plspId = pcepTunnelDBData.plspId();
            }

            tlv = new StatefulIPv4LspIdentidiersTlv((((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
                                                    (short) 0, (short) 0, 0,
                                                    (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
            llOptionalTlv.add(tlv);

            if (tunnel.tunnelName().value() != null) {
                tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
                llOptionalTlv.add(tlv);
            }

            // build lsp object
            PcepLspObject lspobj = pc.factory().buildLspObject().setAFlag(true).setPlspId(plspId)
                    .setOptionalTlv(llOptionalTlv).build();
            // build ero object
            PcepEroObject eroobj = pc.factory().buildEroObject().setSubObjects(llSubObjects).build();

            int iBandwidth = DEFAULT_BANDWIDTH_VALUE;
            if (tunnel.annotations().value("bandwidth") != null) {
                iBandwidth = Integer.parseInt(tunnel.annotations().value("bandwidth"));
            }
            // build bandwidth object
            PcepBandwidthObject bandwidthObject = pc.factory().buildBandwidthObject().setBandwidth(iBandwidth).build();
            // build pcep attribute
            PcepAttribute pcepAttribute = pc.factory().buildPcepAttribute().setBandwidthObject(bandwidthObject).build();
            // build pcep msg path
            PcepMsgPath msgPath = pc.factory().buildPcepMsgPath().setEroObject(eroobj).setPcepAttribute(pcepAttribute)
                    .build();

            PcepUpdateRequest updateRequest = pc.factory().buildPcepUpdateRequest().setSrpObject(srpobj)
                    .setLspObject(lspobj).setMsgPath(msgPath).build();

            llUpdateRequestList.add(updateRequest);

            PcepUpdateMsg pcUpdateMsg = pc.factory().buildUpdateMsg().setUpdateRequestList(llUpdateRequestList).build();

            pc.sendMessage(Collections.singletonList(pcUpdateMsg));
            pcepTunnelApiMapper.addToTunnelRequestQueue(srpId, pcepTunnelData);
        } catch (PcepParseException e) {
            log.error("PcepParseException occurred while processing release tunnel {}", e.getMessage());
        }
    }



    private class InnerTunnelProvider implements PcepTunnelListener, PcepEventListener, PcepClientListener {

        @Override
        public void handlePcepTunnel(PcepTunnel pcepTunnel) {
            TunnelDescription tunnel = null;
            // instance and id identify a tunnel together
            String tunnelKey = String.valueOf(pcepTunnel.getInstance())
                    + String.valueOf(pcepTunnel.id());

            if (tunnelKey == null || "".equals(tunnelKey)) {
                log.error("Invalid PCEP tunnel");
                return;
            }

            TunnelId tunnelId = getTunnelId(tunnelKey);

            tunnel = buildOpticalTunnel(pcepTunnel, tunnelId);

            OperationType operType = pcepTunnel.getOperationType();
            switch (operType) {
            case ADD:
                tunnelId = service.tunnelAdded(tunnel);
                tunnelMap.put(tunnelKey, tunnelId);
                break;

            case UPDATE:
                service.tunnelUpdated(tunnel);
                break;

            case DELETE:
                service.tunnelRemoved(tunnel);
                tunnelMap.remove(tunnelKey);
                break;

            default:
                log.error("Invalid tunnel operation");
            }
        }

        @Override
        public void handleMessage(PccId pccId, PcepMessage msg) {
            try {
                log.debug("tunnel provider handle message {}", msg.getType().toString());
                switch (msg.getType()) {
                case REPORT:
                    int srpId = 0;
                    LinkedList<PcepStateReport> llStateReportList = null;
                    llStateReportList = ((PcepReportMsg) msg).getStateReportList();
                    ListIterator<PcepStateReport> listIterator = llStateReportList.listIterator();
                    PcepSrpObject srpObj = null;
                    PcepLspObject lspObj = null;
                    while (listIterator.hasNext()) {
                        PcepStateReport stateRpt = listIterator.next();
                        srpObj = stateRpt.getSrpObject();
                        lspObj = stateRpt.getLspObject();

                        if (srpObj instanceof PcepSrpObject) {
                            srpId = srpObj.getSrpID();
                        }

                        log.debug("Plsp ID in handle message " + lspObj.getPlspId());
                        log.debug("SRP ID in handle message " + srpId);

                        if (!(pcepTunnelApiMapper.checkFromTunnelRequestQueue(srpId))) {

                            // Check the sync status
                            if (lspObj.getSFlag()) {
                                handleSyncReport(stateRpt);
                            } else if (!pcepClientController.getClient(pccId).isSyncComplete()) {
                                // sync is done
                                pcepClientController.getClient(pccId).setIsSyncComplete(true);
                            }
                            continue;
                        }

                        handleReportMessage(srpId, lspObj);
                    }
                    break;

                default:
                    log.debug("Received unsupported message type {}", msg.getType().toString());
                }
            } catch (Exception e) {
                log.error("Exception occured while processing report message {}", e.getMessage());
            }
        }

        /**
         * Handles report message for setup/update/delete tunnel request.
         *
         * @param srpId unique identifier for pcep message
         * @param lspObj lsp object
         */
        private void handleReportMessage(int srpId, PcepLspObject lspObj) {
            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
            PcepTunnelData pcepTunnelData = pcepTunnelApiMapper.getDataFromTunnelRequestQueue(srpId);
            SparseAnnotations annotations = (SparseAnnotations) pcepTunnelData.tunnel().annotations();

            // store the values required from report message
            pcepTunnelData.setPlspId(lspObj.getPlspId());
            pcepTunnelData.setLspAFlag(lspObj.getAFlag());
            pcepTunnelData.setLspOFlag(lspObj.getOFlag());
            pcepTunnelData.setLspDFlag(lspObj.getDFlag());

            StatefulIPv4LspIdentidiersTlv ipv4LspTlv = null;
            ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
            while (listTlvIterator.hasNext()) {
                PcepValueType tlv = listTlvIterator.next();
                if (tlv.getType() == StatefulIPv4LspIdentidiersTlv.TYPE) {
                    ipv4LspTlv = (StatefulIPv4LspIdentidiersTlv) tlv;
                    break;
                }
            }
            if (ipv4LspTlv != null) {
                pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspTlv);
            }

            Path path = pcepTunnelData.path();
            Tunnel tunnel = pcepTunnelData.tunnel();
            DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(),
                                                                       tunnel.dst(), tunnel.type(), tunnel.groupId(),
                                                                       providerId, tunnel.tunnelName(), path,
                                                                       annotations);

            if (RequestType.CREATE == pcepTunnelData.requestType()) {
                log.debug("Report received for create request");

                pcepTunnelApiMapper.handleCreateTunnelRequestQueue(srpId, pcepTunnelData);
                if (0 == lspObj.getOFlag()) {
                    log.warn("The tunnel is in down state");
                }
                tunnelAdded(td);
            }
            if (RequestType.DELETE == pcepTunnelData.requestType()) {
                log.debug("Report received for delete request");
                pcepTunnelApiMapper.handleRemoveFromTunnelRequestQueue(srpId, pcepTunnelData);
                tunnelRemoved(td);
            }

            if (RequestType.UPDATE == pcepTunnelData.requestType()) {
                log.debug("Report received for update request");
                pcepTunnelData.setRptFlag(true);
                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                pcepTunnelApiMapper.handleUpdateTunnelRequestQueue(srpId, pcepTunnelData);

                if (0 == lspObj.getOFlag()) {
                    log.warn("The tunnel is in down state");
                }
                if (!(pcepTunnelApiMapper.checkFromTunnelRequestQueue(srpId))) {
                    tunnelUpdated(td);
                }
            }
        }

        /**
         * Handles sync report received from pcc.
         *
         * @param stateRpt pcep state report
         */
        private void handleSyncReport(PcepStateReport stateRpt) {
            PcepLspObject lspObj = stateRpt.getLspObject();
            PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
            checkNotNull(msgPath);
            PcepRroObject rroObj = msgPath.getRroObject();
            if (rroObj == null) {
                log.debug("RRO object is null in sate report");
                return;
            }
            int bandwidth = 0;

            log.debug("Handle Sync report received from PCC.");

            if (0 == lspObj.getOFlag()) {
                log.warn("The PCC reported tunnel is in down state");
            }
            log.debug("Sync report received");

            if (msgPath.getBandwidthObject() != null) {
                bandwidth = msgPath.getBandwidthObject().getBandwidth();
            }

            buildAndStorePcepTunnelData(lspObj, rroObj, bandwidth);
        }

        /**
         * To build Path in network from RRO object.
         *
         * @param rroObj rro object
         * @param providerId provider id
         * @return path object
         */
        private Path buildPathFromRroObj(PcepRroObject rroObj, ProviderId providerId) {
            checkNotNull(rroObj);
            List<Link> links = new ArrayList<Link>();
            LinkedList<PcepValueType> llSubObj = rroObj.getSubObjects();
            if (0 == llSubObj.size()) {
                log.error("RRO in report message does not have hop information");
            }
            ListIterator<PcepValueType> tlvIterator = llSubObj.listIterator();

            ConnectPoint src = null;
            ConnectPoint dst = null;
            boolean isSrcSet = false;
            while (tlvIterator.hasNext()) {
                PcepValueType subObj = tlvIterator.next();
                switch (subObj.getType()) {

                case IPv4SubObject.TYPE:

                    IPv4SubObject ipv4SubObj = (IPv4SubObject) subObj;
                    if (!isSrcSet) {
                        IpAddress srcIp = IpAddress.valueOf(ipv4SubObj.getIpAddress());
                        src = new ConnectPoint(IpElementId.ipElement(srcIp), PortNumber.portNumber(0));
                        isSrcSet = true;
                    } else {
                        IpAddress dstIp = IpAddress.valueOf(ipv4SubObj.getIpAddress());
                        dst = new ConnectPoint(IpElementId.ipElement(dstIp), PortNumber.portNumber(0));
                        Link link = DefaultLink.builder()
                                .providerId(providerId)
                                .src(src)
                                .dst(dst)
                                .type(Link.Type.DIRECT)
                                .build();
                        links.add(link);
                        src = dst;
                    }
                    break;
                default:
                    // the other sub objects are not required
                }
            }
            return new DefaultPath(providerId, links, 0, EMPTY);
        }

        /**
         * To build pcepTunnelData and informs core about the pcc reported tunnel.
         *
         * @param lspObj pcep lsp object
         * @param rroObj pcep rro object
         * @param bandwidth bandwidth of tunnel
         */
        private void buildAndStorePcepTunnelData(PcepLspObject lspObj, PcepRroObject rroObj,
                                                 int bandwidth) {

            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);

            // StatefulIPv4LspIdentidiersTlv in LSP object will have the source and destination address.
            StatefulIPv4LspIdentidiersTlv lspIdenTlv = null;
            SymbolicPathNameTlv pathNameTlv = null;
            LinkedList<PcepValueType> llOptionalTlv = lspObj.getOptionalTlv();
            ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();
            while (listIterator.hasNext()) {
                PcepValueType tlv = listIterator.next();
                switch (tlv.getType()) {
                case StatefulIPv4LspIdentidiersTlv.TYPE:
                    lspIdenTlv = (StatefulIPv4LspIdentidiersTlv) tlv;
                    break;
                case SymbolicPathNameTlv.TYPE:
                    pathNameTlv = (SymbolicPathNameTlv) tlv;
                    break;
                default:
                    // currently this tlv is not required
                }
            }

            IpTunnelEndPoint tunnelEndPointSrc;
            tunnelEndPointSrc = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4IngressAddress()));
            IpTunnelEndPoint tunnelEndPointDst;
            tunnelEndPointDst = IpTunnelEndPoint.ipTunnelPoint(IpAddress.valueOf(lspIdenTlv.getIpv4EgressAddress()));

            Path path = buildPathFromRroObj(rroObj, providerId);

            SparseAnnotations annotations = DefaultAnnotations.builder()
                    .set("bandwidth", (new Integer(bandwidth)).toString())
                    .build();

            DefaultTunnelDescription td = new DefaultTunnelDescription(null, tunnelEndPointSrc,
                                                                       tunnelEndPointDst, Tunnel.Type.MPLS,
                                                                       new DefaultGroupId(0), providerId,
                                                                       TunnelName.tunnelName(pathNameTlv.toString()),
                                                                       path, annotations);
            TunnelId tId = tunnelAdded(td);

            Tunnel tunnel = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, Tunnel.Type.MPLS,
                                              new DefaultGroupId(0), tId,
                                              TunnelName.tunnelName(pathNameTlv.toString()), path, annotations);

            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, RequestType.LSP_STATE_RPT);
            pcepTunnelData.setStatefulIpv4IndentifierTlv(lspIdenTlv);
            pcepTunnelApiMapper.addPccTunnelDB(pcepTunnelData);
            pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
        }

        @Override
        public void clientConnected(PccId pccId) {
            // TODO
        }

        @Override
        public void clientDisconnected(PccId pccId) {
            // TODO
        }



        @Override
        public void handlePcepTunnelStatistics(PcepTunnelStatistics pcepTunnelStatistics) {
            TunnelId id = getTunnelId(String.valueOf(pcepTunnelStatistics.id()));
            TunnelStatistics tunnelStatistics = buildTunnelStatistics(pcepTunnelStatistics);
            tunnelStatisticsMap.put(id, tunnelStatistics);
        }
    }

    @Override
    public Tunnel tunnelQueryById(TunnelId tunnelId) {
        return service.tunnelQueryById(tunnelId);
    }
}
