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

import com.google.common.collect.Maps;
import org.onlab.graph.ScalarWeight;
import org.onlab.packet.Ip4Address;
import org.onlab.packet.IpAddress;
import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.GroupId;
import org.onosproject.incubator.net.resource.label.LabelResourceId;
import org.onosproject.incubator.net.tunnel.DefaultLabelStack;
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.Tunnel.State;
import org.onosproject.incubator.net.tunnel.TunnelAdminService;
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.mastership.MastershipService;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.DefaultAnnotations.Builder;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DefaultPath;
import org.onosproject.net.Device;
import org.onosproject.net.DeviceId;
import org.onosproject.net.ElementId;
import org.onosproject.net.IpElementId;
import org.onosproject.net.Link;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.SparseAnnotations;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.link.LinkService;
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.server.LspKey;
import org.onosproject.pcep.server.LspType;
import org.onosproject.pcep.server.PccId;
import org.onosproject.pcep.server.PcepClient;
import org.onosproject.pcep.server.PcepClientController;
import org.onosproject.pcep.server.PcepClientListener;
import org.onosproject.pcep.server.PcepEventListener;
import org.onosproject.pcep.server.PcepLspStatus;
import org.onosproject.pcep.server.PcepLspSyncAction;
import org.onosproject.pcep.server.PcepSyncStatus;
import org.onosproject.pcep.server.SrpIdGenerators;
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.PcepMetricObject;
import org.onosproject.pcepio.protocol.PcepMsgPath;
import org.onosproject.pcepio.protocol.PcepReportMsg;
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.PathSetupTypeTlv;
import org.onosproject.pcepio.types.PcepNaiIpv4Adjacency;
import org.onosproject.pcepio.types.PcepValueType;
import org.onosproject.pcepio.types.SrEroSubObject;
import org.onosproject.pcepio.types.StatefulIPv4LspIdentifiersTlv;
import org.onosproject.pcepio.types.SymbolicPathNameTlv;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.slf4j.Logger;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
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.Objects;
import java.util.Optional;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

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.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.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.onosproject.pcep.server.LspType.SR_WITHOUT_SIGNALLING;
import static org.onosproject.pcep.server.LspType.WITHOUT_SIGNALLING_AND_WITHOUT_SR;
import static org.onosproject.pcep.server.LspType.WITH_SIGNALLING;
import static org.onosproject.pcep.server.PcepAnnotationKeys.BANDWIDTH;
import static org.onosproject.pcep.server.PcepAnnotationKeys.COST_TYPE;
import static org.onosproject.pcep.server.PcepAnnotationKeys.DELEGATE;
import static org.onosproject.pcep.server.PcepAnnotationKeys.LOCAL_LSP_ID;
import static org.onosproject.pcep.server.PcepAnnotationKeys.LSP_SIG_TYPE;
import static org.onosproject.pcep.server.PcepAnnotationKeys.PCC_TUNNEL_ID;
import static org.onosproject.pcep.server.PcepAnnotationKeys.PCE_INIT;
import static org.onosproject.pcep.server.PcepAnnotationKeys.PLSP_ID;
import static org.onosproject.pcep.server.PcepLspSyncAction.REMOVE;
import static org.onosproject.pcep.server.PcepLspSyncAction.SEND_UPDATE;
import static org.onosproject.pcepio.protocol.ver1.PcepMetricObjectVer1.IGP_METRIC;
import static org.onosproject.pcepio.protocol.ver1.PcepMetricObjectVer1.TE_METRIC;
import static org.onosproject.provider.pcep.tunnel.impl.OsgiPropertyConstants.POLL_FREQUENCY;
import static org.onosproject.provider.pcep.tunnel.impl.OsgiPropertyConstants.POLL_FREQUENCY_DEFAULT;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.CREATE;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.DELETE;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.LSP_STATE_RPT;
import static org.onosproject.provider.pcep.tunnel.impl.RequestType.UPDATE;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Provider which uses an PCEP controller to detect, update, create network
 * tunnels.
 */
@Component(immediate = true, service = TunnelProvider.class,
        property = {
                POLL_FREQUENCY + ":Integer=" + POLL_FREQUENCY_DEFAULT,
        })
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";
    public static final long IDENTIFIER_SET = 0x100000000L;
    public static final long SET = 0xFFFFFFFFL;
    private static final int DELAY = 2;
    private static final int WAIT_TIME = 5;
    public static final String LSRID = "lsrId";

    /** Frequency (in seconds) for polling tunnel statistics. */
    private int tunnelStatsPollFrequency = POLL_FREQUENCY_DEFAULT;

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

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

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

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

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

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

    @Reference(cardinality = ReferenceCardinality.MANDATORY)
    protected TunnelAdminService tunnelAdminService;

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

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

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

    TunnelProviderService service;

    HashMap<String, TunnelId> tunnelMap = new HashMap<>();
    HashMap<TunnelId, TunnelStatistics> tunnelStatisticsMap = new HashMap<>();
    private HashMap<String, 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, POLL_FREQUENCY);
            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() != 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 == null) {
            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
        //Only master will initiate setup tunnel
        if (pc.capability().pcInstantiationCapability() && mastershipService.isLocalMaster(getDevice(pc.getPccId()))) {
            pcepSetupTunnel(tunnel, path, pc);
        }
    }

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

        //TODO: tunnel which is passed doesn't have tunnelID
        if (tunnel.annotations().value(PLSP_ID) != null) {
            if (LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)) != WITHOUT_SIGNALLING_AND_WITHOUT_SR) {
                updateTunnel(tunnel, path);
            } else {
                // Download labels and send update message.
                // To get new tunnel ID (modified tunnel ID)
                Collection<Tunnel> tunnels = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
                for (Tunnel t : tunnels) {
                    if (t.state().equals(INIT) && t.tunnelName().equals(tunnel.tunnelName())) {
                        tunnel = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
                                tunnel.dst(), tunnel.type(),
                                t.state(), tunnel.groupId(),
                                t.tunnelId(),
                                tunnel.tunnelName(),
                                tunnel.path(),
                                tunnel.resource(),
                                tunnel.annotations());
                                break;
                    }
                }
                if (!pcepClientController.allocateLocalLabel(tunnel)) {
                    log.error("Unable to allocate labels for the tunnel {}.", tunnel.toString());
                }
            }
            return;
        }

        if (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 == null) {
            log.error("There is no PCC connected with this device {}"
                    + srcElement.toString());
            return;
        }

        //If stateful and PC Initiation capability is not supported by client not sending Initiate msg
        //Only master will initiate setup tunnel
        if (pc.capability().pcInstantiationCapability()
                && mastershipService.isLocalMaster(getDevice(pc.getPccId()))) {
            pcepSetupTunnel(tunnel, path, pc);
        }
    }

    @Override
    public void releaseTunnel(Tunnel tunnel) {

        if (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 == null) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpTunnelEndPoint) tunnel.src()).ip().toString());
            return;
        }

        //Only master will release tunnel
        if (pc.capability().pcInstantiationCapability()
                && mastershipService.isLocalMaster(getDevice(pc.getPccId()))) {
            pcepReleaseTunnel(tunnel, pc);
        }
    }

    @Override
    public void releaseTunnel(ElementId srcElement, Tunnel tunnel) {
        if (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 == null) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpElementId) srcElement).ipAddress().toString());
            return;
        }

        //Only master will release tunnel
        if (pc.capability().pcInstantiationCapability()
                && mastershipService.isLocalMaster(getDevice(pc.getPccId()))) {
            pcepReleaseTunnel(tunnel, pc);
        }
    }

    @Override
    public void updateTunnel(Tunnel tunnel, Path path) {
        if (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;
        }

        //To get new tunnel ID (modified tunnel ID)
        Collection<Tunnel> tunnels = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
        for (Tunnel t : tunnels) {
            if (t.state().equals(INIT) && t.tunnelName().equals(tunnel.tunnelName())) {
                tunnel = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
                        tunnel.dst(), tunnel.type(),
                        t.state(), tunnel.groupId(),
                        t.tunnelId(),
                        tunnel.tunnelName(),
                        tunnel.path(),
                        tunnel.resource(),
                        tunnel.annotations());
                        break;
            }
        }

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

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

        //PCInitiate tunnels are always have D flag set, else check for tunnels who are delegated via LspKey
        if (pc.capability().statefulPceCapability()) {
            if (tunnel.annotations().value(PCE_INIT) != null && tunnel.annotations().value(PCE_INIT).equals("true")) {
                pcepUpdateTunnel(tunnel, path, pc);
            } else {
                // If delegation flag is set then only send update message[means delegated PCE can send update msg for
                // that LSP. If annotation is null D flag is not set else it is set.
                Short localLspId = 0;
                for (Tunnel t : tunnels) {
                    if (!t.tunnelId().equals(tunnel.tunnelId()) && t.tunnelName().equals(tunnel.tunnelName())) {
                        localLspId = Short.valueOf(t.annotations().value(LOCAL_LSP_ID));
                    }
                }

                if (localLspId == 0) {
                    log.error("Local LSP ID for old tunnel not found");
                    return;
                }

                if (pc.delegationInfo(new LspKey(Integer.valueOf(tunnel.annotations().value(PLSP_ID)),
                                                 localLspId.shortValue())) != null) {

                    pcepUpdateTunnel(tunnel, path, pc);
                }
            }
        }
    }

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

        if (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 == null) {
            log.error("There is no PCC connected with ip addresss {}"
                    + ((IpElementId) srcElement).ipAddress().toString());
            return;
        }

        // If delegation flag is set then only send update message[means delegated PCE can send update msg for that
        // LSP].If annotation is null D flag is not set else it is set.
        if (pc.capability().statefulPceCapability()
                && pc.delegationInfo(
                        new LspKey(Integer.valueOf(tunnel.annotations().value(PLSP_ID)), Short.valueOf(tunnel
                                .annotations().value(LOCAL_LSP_ID)))) != null) {
            pcepUpdateTunnel(tunnel, path, pc);
        }
    }

    @Override
    public TunnelId tunnelAdded(TunnelDescription tunnel) {
        return handleTunnelAdded(tunnel, null);
    }

    public TunnelId tunnelAdded(TunnelDescription tunnel, State tunnelState) {
        return handleTunnelAdded(tunnel, tunnelState);
    }

    private TunnelId handleTunnelAdded(TunnelDescription tunnel, State tunnelState) {

        if (tunnel.type() == MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.id());

            if (tunnelState == null) {
                return service.tunnelAdded(tunnel);
            } else {
                return service.tunnelAdded(tunnel, tunnelState);
            }
        }

        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;
    }

    private void tunnelUpdated(Tunnel tunnel, Path path, State tunnelState) {
        handleTunnelUpdate(tunnel, path, tunnelState);
    }

    //Handles tunnel updated using tunnel admin service[specially to update annotations].
    private void handleTunnelUpdate(Tunnel tunnel, Path path, State tunnelState) {

        if (tunnel.type() == MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.tunnelId());

            TunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(), tunnel.dst(),
                    tunnel.type(), tunnel.groupId(), tunnel.providerId(),
                    tunnel.tunnelName(), path, tunnel.resource(),
                    (SparseAnnotations) tunnel.annotations());

            service.tunnelUpdated(td, tunnelState);
            return;
        }

        Tunnel tunnelOld = tunnelQueryById(tunnel.tunnelId());
        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.tunnelId());

        checkNotNull(pcepTunnelId, "Invalid tunnel id");
        if (!controller.updateTunnelBandwidth(pcepTunnelId, bandwidth)) {
            error("Update failed,maybe invalid bandwidth.");
            return;
        }
        tunnelAdminService.updateTunnel(tunnel, path);
    }

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

        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) {
        handleTunnelUpdate(tunnel, null);
    }

    public void tunnelUpdated(TunnelDescription tunnel, State tunnelState) {
        handleTunnelUpdate(tunnel, tunnelState);
    }

    private void handleTunnelUpdate(TunnelDescription tunnel, State tunnelState) {
        if (tunnel.type() == MPLS) {
            pcepTunnelApiMapper.removeFromCoreTunnelRequestQueue(tunnel.id());

            if (tunnelState == null) {
                service.tunnelUpdated(tunnel);
            } else {
                service.tunnelUpdated(tunnel, tunnelState);
            }
            return;
        }

        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.isEmpty()) {
            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, ScalarWeight.toWeight(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 GroupId(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 (Objects.equals(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 ERO subobjects
     */
    private LinkedList<PcepValueType> createPcepPath(Path path) {
        LinkedList<PcepValueType> llSubObjects = new LinkedList<>();
        List<Link> listLink = path.links();
        ConnectPoint source = null;
        ConnectPoint destination = null;
        IpAddress ipDstAddress = null;
        IpAddress ipSrcAddress = null;
        PcepValueType subObj = null;
        long portNo;

        for (Link link : listLink) {
            source = link.src();
            if (!(source.equals(destination))) {
                //set IPv4SubObject for ERO object
                portNo = source.port().toLong();
                portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
                ipSrcAddress = Ip4Address.valueOf((int) portNo);
                subObj = new IPv4SubObject(ipSrcAddress.getIp4Address().toInt());
                llSubObjects.add(subObj);
            }

            destination = link.dst();
            portNo = destination.port().toLong();
            portNo = ((portNo & IDENTIFIER_SET) == IDENTIFIER_SET) ? portNo & SET : portNo;
            ipDstAddress = Ip4Address.valueOf((int) portNo);
            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 = null;
        LspType lspType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));

        if (lspType == SR_WITHOUT_SIGNALLING) {
            NetworkResource labelStack = tunnel.resource();
            if (labelStack == null || !(labelStack instanceof DefaultLabelStack)) {
                labelStack = pcepClientController.computeLabelStack(tunnel.path());
                if (labelStack == null) {
                    log.error("Unable to create label stack.");
                    return null;
                }
            }
            llSubObjects = pcepClientController.createPcepLabelStack((DefaultLabelStack) labelStack, path);
        } else {
            llSubObjects = createPcepPath(path);
        }

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

        LinkedList<PcepValueType> llOptionalTlv = new LinkedList<>();

        // set PathSetupTypeTlv of SRP object
        tlv = new PathSetupTypeTlv(lspType.type());
        llOptionalTlv.add(tlv);

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

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

        // set LSP identifiers TLV
        short localLspId = 0;
        if (LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)) != WITH_SIGNALLING) {
            String localLspIdString = tunnel.annotations().value(LOCAL_LSP_ID);
            if (localLspIdString != null) {
                localLspId = Short.valueOf(localLspIdString);
            }
        }

        tunnel.annotations().value(LSP_SIG_TYPE);
        tlv = new StatefulIPv4LspIdentifiersTlv((((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt()),
                                                localLspId, (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).setDFlag(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();

        float  iBandwidth = DEFAULT_BANDWIDTH_VALUE;
        if (tunnel.annotations().value(BANDWIDTH) != null) {
            iBandwidth = Float.valueOf(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 {
            if (!(pc.lspDbSyncStatus().equals(PcepSyncStatus.SYNCED))) {
                log.error("Setup tunnel has failed as LSP DB sync is not finished");
                return;
            }

            int srpId = SrpIdGenerators.create();
            Collection<Tunnel> tunnels = tunnelService.queryTunnel(tunnel.src(), tunnel.dst());
            for (Tunnel t : tunnels) {
                if (t.tunnelName().equals(tunnel.tunnelName())) {
                    tunnel = new DefaultTunnel(tunnel.providerId(), tunnel.src(),
                            tunnel.dst(), tunnel.type(),
                            t.state(), tunnel.groupId(),
                            t.tunnelId(),
                            tunnel.tunnelName(),
                            tunnel.path(),
                            tunnel.resource(),
                            tunnel.annotations());
                            break;
                }
            }

            if (tunnel.tunnelId() == null) {
                log.error("Tunnel ID not found");
                return;
            }

            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, path, CREATE);

            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);

            LinkedList<PcInitiatedLspRequest> llPcInitiatedLspRequestList = createPcInitiatedLspReqList(tunnel, path,
                                                                                                        pc, srpId);
            if (llPcInitiatedLspRequestList == null || llPcInitiatedLspRequestList.isEmpty()) {
                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 {
            if (!(pc.lspDbSyncStatus().equals(PcepSyncStatus.SYNCED))) {
                log.error("Release tunnel has failed as LSP DB sync is not finished");
                return;
            }

            PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, DELETE);
            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
            int srpId = SrpIdGenerators.create();

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

            // set PathSetupTypeTlv of SRP object
            tlv = new PathSetupTypeTlv(LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE))
                    .type());
            llOptionalTlv.add(tlv);

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

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

            tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
            llOptionalTlv.add(tlv);

            String localLspIdString = tunnel.annotations().value(LOCAL_LSP_ID);
            String pccTunnelIdString = tunnel.annotations().value(PCC_TUNNEL_ID);
            String pLspIdString = tunnel.annotations().value(PLSP_ID);

            short localLspId = 0;
            short pccTunnelId = 0;
            int plspId = 0;

            if (localLspIdString != null) {
                localLspId = Short.valueOf(localLspIdString);
            }

            if (pccTunnelIdString != null) {
                pccTunnelId = Short.valueOf(pccTunnelIdString);
            }

            if (pLspIdString != null) {
                plspId = Integer.valueOf(pLspIdString);
            }

            tlv = new StatefulIPv4LspIdentifiersTlv((((IpTunnelEndPoint) tunnel.src())
                    .ip().getIp4Address().toInt()),
                    localLspId, pccTunnelId, 0, (((IpTunnelEndPoint) tunnel.dst()).ip()
                    .getIp4Address().toInt()));
            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, UPDATE);
            pcepTunnelApiMapper.addToCoreTunnelRequestQueue(pcepTunnelData);
            int srpId = SrpIdGenerators.create();
            PcepValueType tlv;

            LinkedList<PcepValueType> llSubObjects = null;
            LspType lspSigType = LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE));

            if (lspSigType == SR_WITHOUT_SIGNALLING) {
                NetworkResource labelStack = tunnel.resource();
                if (labelStack == null || !(labelStack instanceof DefaultLabelStack)) {
                    labelStack = pcepClientController.computeLabelStack(tunnel.path());
                    if (labelStack == null) {
                        log.error("Unable to create label stack.");
                        return;
                    }
                }
                llSubObjects = pcepClientController.createPcepLabelStack((DefaultLabelStack) labelStack, path);
            } else {
                llSubObjects = createPcepPath(path);
            }

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

            // set PathSetupTypeTlv of SRP object
            tlv = new PathSetupTypeTlv(lspSigType.type());
            llOptionalTlv.add(tlv);

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

            llOptionalTlv = new LinkedList<>();

            // Lsp Identifier tlv is required for all modes of lsp
            String localLspIdString = tunnel.annotations().value(LOCAL_LSP_ID);
            String pccTunnelIdString = tunnel.annotations().value(PCC_TUNNEL_ID);
            short localLspId = 0;
            short pccTunnelId = 0;

            if (localLspIdString != null) {
                localLspId = Short.valueOf(localLspIdString);
            }

            if (pccTunnelIdString != null) {
                pccTunnelId = Short.valueOf(pccTunnelIdString);
            }

            tlv = new StatefulIPv4LspIdentifiersTlv((((IpTunnelEndPoint) tunnel.src())
                    .ip().getIp4Address().toInt()),
                    localLspId, pccTunnelId,
                    ((IpTunnelEndPoint) tunnel.src()).ip().getIp4Address().toInt(),
                    (((IpTunnelEndPoint) tunnel.dst()).ip().getIp4Address().toInt()));
            llOptionalTlv.add(tlv);

            if (tunnel.tunnelName().value() != null) {
                tlv = new SymbolicPathNameTlv(tunnel.tunnelName().value().getBytes());
                llOptionalTlv.add(tlv);
            }
            boolean delegated = (tunnel.annotations().value(DELEGATE) == null) ? false
                                                                               : Boolean.valueOf(tunnel.annotations()
                                                                                       .value(DELEGATE));
            boolean initiated = (tunnel.annotations().value(PCE_INIT) == null) ? false
                                                                               : Boolean.valueOf(tunnel.annotations()
                                                                                       .value(PCE_INIT));
            // build lsp object
            PcepLspObject lspobj = pc.factory().buildLspObject().setAFlag(true)
                    .setPlspId(Integer.valueOf(tunnel.annotations().value(PLSP_ID)))
                    .setDFlag(delegated)
                    .setCFlag(initiated)
                    .setOptionalTlv(llOptionalTlv).build();
            // build ero object
            PcepEroObject eroobj = pc.factory().buildEroObject().setSubObjects(llSubObjects).build();
            float iBandwidth = DEFAULT_BANDWIDTH_VALUE;
            if (tunnel.annotations().value(BANDWIDTH) != null) {
                iBandwidth = Float.parseFloat(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 != null) {
                            srpId = srpObj.getSrpID();
                        }

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

                        if (!(pcepTunnelApiMapper.checkFromTunnelRequestQueue(srpId))) {
                            // For PCRpt without matching SRP id.
                            handleRptWithoutSrpId(stateRpt, pccId);
                            continue;
                        }

                        handleReportMessage(srpId, lspObj, stateRpt);
                    }
                    break;

                default:
                    log.debug("Received unsupported message type {}", msg.getType().toString());
                }
            } catch (Exception e) {
                log.error("Exception occurred 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
         * @param stateRpt parsed PCEP report msg.
         */
        private void handleReportMessage(int srpId, PcepLspObject lspObj, PcepStateReport stateRpt) {
            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
            PcepTunnelData pcepTunnelData = pcepTunnelApiMapper.getDataFromTunnelRequestQueue(srpId);

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

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

            Path path = pcepTunnelData.path();
            Tunnel tunnel = pcepTunnelData.tunnel();
            Builder annotationBuilder = DefaultAnnotations.builder();
            annotationBuilder.putAll(pcepTunnelData.tunnel().annotations());

            // PCRpt in response to PCInitate msg will carry PLSP id allocated by PCC.
            if (tunnel.annotations().value(PLSP_ID) == null) {
                annotationBuilder.set(PLSP_ID, String.valueOf(lspObj.getPlspId()));
            }

            // Signalled LSPs will carry local LSP id allocated by signalling protocol(PCC).
            if (tunnel.annotations().value(LOCAL_LSP_ID) == null) {
                annotationBuilder.set(LOCAL_LSP_ID, String.valueOf(ipv4LspTlv.getLspId()));
            }

            if (tunnel.annotations().value(PCC_TUNNEL_ID) == null) {
                annotationBuilder.set(PCC_TUNNEL_ID, String.valueOf(ipv4LspTlv.getTunnelId()));
            }

            SparseAnnotations annotations = annotationBuilder.build();
            DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(),
                                                                       tunnel.dst(), tunnel.type(), tunnel.groupId(),
                                                                       providerId, tunnel.tunnelName(), path,
                                                                       tunnel.resource(), annotations);

            if (CREATE == pcepTunnelData.requestType()) {
                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                pcepTunnelApiMapper.handleCreateTunnelRequestQueue(srpId, pcepTunnelData);
            } else if (DELETE == pcepTunnelData.requestType()) {
                pcepTunnelApiMapper.handleRemoveFromTunnelRequestQueue(srpId, pcepTunnelData);
            } else if (UPDATE == pcepTunnelData.requestType()) {
                pcepTunnelData.setRptFlag(true);
                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                pcepTunnelApiMapper.handleUpdateTunnelRequestQueue(srpId, pcepTunnelData);
            }

            PcepLspStatus pcepLspStatus = PcepLspStatus.values()[lspObj.getOFlag()];

            if (lspObj.getRFlag()) {
                tunnelRemoved(td);
            } else {
                State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(pcepLspStatus);
                tunnelUpdated(td, tunnelState);
            }

            // SR-TE also needs PCUpd msg after receiving PCRpt with status GOING-UP even
            // though there are no labels to download for SR-TE.
            if (((pcepLspStatus == PcepLspStatus.GOING_UP)
                    && (LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)) == SR_WITHOUT_SIGNALLING))
                // For PCInit tunnel up, few PCC expects PCUpd message after PCInit message,
                || ((tunnel.state() == State.INIT)
                    && (pcepLspStatus == PcepLspStatus.DOWN)
                    && (tunnel.annotations().value(PCE_INIT) != null
                        && tunnel.annotations().value(PCE_INIT).equals("true"))
                    && (LspType.valueOf(tunnel.annotations().value(LSP_SIG_TYPE)) == WITH_SIGNALLING))) {

                // Query again to get latest tunnel updated with protocol values from PCRpt msg.
                updateTunnel(service.tunnelQueryById(tunnel.tunnelId()), tunnel.path());
            }
        }

        private SparseAnnotations getAnnotations(PcepLspObject lspObj, StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv,
                String bandwidth, LspType lspType, String costType, boolean isPceInit) {
            Builder builder = DefaultAnnotations.builder();
            /*
             * [RFC 5440] The absence of the METRIC object MUST be interpreted by the PCE as a path computation request
             * for which no constraints need be applied to any of the metrics.
             */
            if (costType != null) {
                builder.set(COST_TYPE, costType);
            }

            if (isPceInit) {
                builder.set(PCE_INIT, String.valueOf(isPceInit));
            }

            if (bandwidth != null) {
                builder.set(BANDWIDTH, bandwidth);
            }

            SparseAnnotations annotations = builder
                    .set(LSP_SIG_TYPE, lspType.name())
                    .set(PCC_TUNNEL_ID, String.valueOf(ipv4LspIdenTlv.getTunnelId()))
                    .set(PLSP_ID, String.valueOf(lspObj.getPlspId()))
                    .set(LOCAL_LSP_ID, String.valueOf(ipv4LspIdenTlv.getLspId()))
                    .set(DELEGATE, String.valueOf(lspObj.getDFlag()))
                    .build();
            return annotations;
        }

        private LspType getLspType(PcepSrpObject srpObj) {
            LspType lspType = WITH_SIGNALLING;

            if (null != srpObj) {
                LinkedList<PcepValueType> llOptionalTlv = srpObj.getOptionalTlv();
                ListIterator<PcepValueType> listIterator = llOptionalTlv.listIterator();

                while (listIterator.hasNext()) {
                    PcepValueType tlv = listIterator.next();
                    switch (tlv.getType()) {
                    case PathSetupTypeTlv.TYPE:
                        lspType = LspType.values()[Integer.valueOf(((PathSetupTypeTlv) tlv).getPst())];
                        break;
                    default:
                        break;
                    }
                }
            }
            return lspType;
        }

        private void handleRptWithoutSrpId(PcepStateReport stateRpt, PccId pccId) {
            ProviderId providerId = new ProviderId("pcep", PROVIDER_ID);
            String costType = null;
            PcepStateReport.PcepMsgPath msgPath = stateRpt.getMsgPath();
            checkNotNull(msgPath);
            PcepEroObject eroObj = msgPath.getEroObject();
            if (eroObj == null) {
                log.error("ERO object is null in report message.");
                return;
            }
            PcepAttribute attributes = msgPath.getPcepAttribute();
            float bandwidth = 0;
            int cost = 0;
            if (attributes != null) {
                if (attributes.getMetricObjectList() != null) {
                    ListIterator<PcepMetricObject> iterator = attributes.getMetricObjectList().listIterator();
                    PcepMetricObject metricObj = iterator.next();

                    while (metricObj != null) {
                        if (metricObj.getBType() == IGP_METRIC) {
                            costType = "COST";
                        } else if (metricObj.getBType() == TE_METRIC) {
                            costType = "TE_COST";
                        }
                        if (costType != null) {
                            cost = metricObj.getMetricVal();
                            log.debug("Path cost {}", cost);
                            break;
                        }
                        metricObj = iterator.next();
                    }
                }
                if (attributes.getBandwidthObject() != null) {
                    bandwidth = attributes.getBandwidthObject().getBandwidth();
                }
            }
            PcepLspObject lspObj = stateRpt.getLspObject();
            List<Object> eroSubObjList = buildPathFromEroObj(eroObj, providerId);
            List<Link> links = new ArrayList<>();
            List<LabelResourceId> labels = new ArrayList<>();
            for (Object linkOrLabel : eroSubObjList) {
                if (linkOrLabel instanceof Link) {
                    links.add((Link) linkOrLabel);
                } else if (linkOrLabel instanceof Integer) {
                    labels.add(LabelResourceId.labelResourceId(((Integer) linkOrLabel).longValue()));
                }
            }
            Path path = null;
            if (!links.isEmpty()) {
                path = new DefaultPath(providerId, links, ScalarWeight.toWeight(cost), EMPTY);
            } else if (!lspObj.getRFlag()) {
                return;
            }
            NetworkResource labelStack = new DefaultLabelStack(labels);
            // To carry PST TLV, SRP object can be present with value 0 even when PCRpt is not in response to any action
            // from PCE.
            PcepSrpObject srpObj = stateRpt.getSrpObject();
            LspType lspType = getLspType(srpObj);
            ListIterator<PcepValueType> listTlvIterator = lspObj.getOptionalTlv().listIterator();
            StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv = null;
            SymbolicPathNameTlv pathNameTlv = null;
            while (listTlvIterator.hasNext()) {
                PcepValueType tlv = listTlvIterator.next();
                switch (tlv.getType()) {
                case StatefulIPv4LspIdentifiersTlv.TYPE:
                    ipv4LspIdenTlv = (StatefulIPv4LspIdentifiersTlv) tlv;
                    break;
                case SymbolicPathNameTlv.TYPE:
                    pathNameTlv = (SymbolicPathNameTlv) tlv;
                    break;
                default:
                    break;
                }
            }
            /*
             * Draft says: The LSP-IDENTIFIERS TLV MUST be included in the LSP object in PCRpt messages for
             * RSVP-signaled LSPs. For ONOS PCECC implementation, it is mandatory.
             */
            if (ipv4LspIdenTlv == null) {
                log.error("Stateful IPv4 identifier TLV is null in PCRpt msg.");
                return;
            }
            IpTunnelEndPoint tunnelEndPointSrc = IpTunnelEndPoint
                    .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4IngressAddress()));
            IpTunnelEndPoint tunnelEndPointDst = IpTunnelEndPoint
                    .ipTunnelPoint(IpAddress.valueOf(ipv4LspIdenTlv.getIpv4EgressAddress()));
            Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(tunnelEndPointSrc, tunnelEndPointDst);
            // Store delegation flag info and that LSP info because only delegated PCE sends update message
            // Storing if D flag is set, if not dont store. while checking whether delegation if annotation for D flag
            // not present then non-delegated , if present it is delegated.
            if (lspObj.getDFlag()) {
                pcepClientController.getClient(pccId).setLspAndDelegationInfo(
                        new LspKey(lspObj.getPlspId(), ipv4LspIdenTlv.getLspId()), lspObj.getDFlag());
            }
            Tunnel tunnel = null;
            SparseAnnotations oldTunnelAnnotations = null;
            // Asynchronous status change message from PCC for LSP reported earlier.
            for (Tunnel tunnelObj : tunnelQueryResult) {
                if (tunnelObj.annotations().value(PLSP_ID) == null) {
                    /*
                     * PLSP_ID is null while Tunnel is created at PCE and PCInit msg carries it as 0. It is allocated by
                     * PCC and in that case it becomes the first PCRpt msg from PCC for this LSP, and hence symbolic
                     * path name must be carried in the PCRpt msg. Draft says: The SYMBOLIC-PATH-NAME TLV "MUST" be
                     * included in the LSP object in the LSP State Report (PCRpt) message when during a given PCEP
                     * session an LSP is "first" reported to a PCE.
                     */
                    if ((pathNameTlv != null)
                            && Arrays.equals(tunnelObj.tunnelName().value().getBytes(), pathNameTlv.getValue())) {
                        tunnel = tunnelObj;
                        break;
                    }
                    continue;
                }
                if ((Integer.valueOf(tunnelObj.annotations().value(PLSP_ID)) == lspObj.getPlspId())) {
                    if ((Integer
                            .valueOf(tunnelObj.annotations().value(LOCAL_LSP_ID)) == ipv4LspIdenTlv.getLspId())) {
                        tunnel = tunnelObj;
                    }
                    if ((Integer
                            .valueOf(tunnelObj.annotations().value(LOCAL_LSP_ID)) != ipv4LspIdenTlv.getLspId())) {
                        oldTunnelAnnotations = (SparseAnnotations) tunnelObj.annotations();
                    }
                }
            }
            DefaultTunnelDescription td;
            SparseAnnotations annotations = null;
            State tunnelState = PcepLspStatus.getTunnelStatusFromLspStatus(PcepLspStatus.values()[lspObj.getOFlag()]);
            if (tunnel == null && pathNameTlv != null) {
                if (lspObj.getRFlag()) {
                    /*
                     * If PCC sends remove message and for any reason PCE does not have that entry, simply discard the
                     * message. Or if PCRpt for initiated LSP received and PCE doesn't know, then too discard.
                     */
                    return;
                }
                DeviceId deviceId = getDevice(pccId);
                if (deviceId == null) {
                    log.error("Ingress deviceId not found");
                    return;
                }
                String tempBandwidth = null;
                String temoCostType = null;
                if (oldTunnelAnnotations != null) {
                    tempBandwidth = oldTunnelAnnotations.value(BANDWIDTH);
                    temoCostType = oldTunnelAnnotations.value(COST_TYPE);
                }
                annotations = getAnnotations(lspObj, ipv4LspIdenTlv, tempBandwidth, lspType,
                    temoCostType, lspObj.getCFlag());
                td = new DefaultTunnelDescription(null, tunnelEndPointSrc, tunnelEndPointDst, MPLS, new GroupId(
                        0), providerId, TunnelName.tunnelName(new String(pathNameTlv.getValue())), path, labelStack,
                        annotations);
                // Do not support PCC initiated LSP after LSP DB sync is completed.
                if (!lspObj.getSFlag() && !lspObj.getCFlag()) {
                    log.error("Received PCC initiated LSP while not in sync.");
                    return;
                }
                /*
                 * If ONOS instance is master for PCC then set delegated flag as annotation and add the tunnel to store.
                 * Because all LSPs need not be delegated, hence mastership for the PCC is confirmed whereas not the
                 * delegation set to all LSPs.If ONOS is not the master for that PCC then check if D flag is set, if yes
                 * wait for 2 seconds [while master has added the tunnel to the store] then update the tunnel. Tunnel is
                 * updated because in case of resilency only delegated LSPs are recomputed and only delegated PCE can
                 * send update message to that client.
                 *
                 * 1)Master can 1st get the Rpt message
                 * a)Master adds the tunnel into core.
                 * b)If a non-master for ingress gets Rpt message with D flag set[as delegation owner]
                 *  after master, then runs timer then update the tunnel with D flag set.
                 * 2)Non-Master can 1st get the Rpt message
                 * a)Non-Master runs the timer check for the tunnel then updates the tunnel with D flag set
                 * b)Master would have got the message while the non-master running timer, hence master adds
                 *  tunnel to core
                 *
                 * In general always master adds the tunnel to the core
                 * while delegated owner [master or non-master with D flag set] always updates the tunnel running timer
                 */
                if (mastershipService.isLocalMaster(deviceId)) {
                    TunnelId tId = tunnelAdded(td, tunnelState);
                    Tunnel tunnelInserted = new DefaultTunnel(providerId, tunnelEndPointSrc, tunnelEndPointDst, MPLS,
                            tunnelState, new GroupId(0), tId, TunnelName.tunnelName(Arrays.toString(pathNameTlv
                                    .getValue())), path, labelStack, annotations);

                    PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnelInserted, path, LSP_STATE_RPT);
                    pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdenTlv);
                    pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                } else if (!mastershipService.isLocalMaster(deviceId) && lspObj.getDFlag()) {
                    //Start timer then update the tunnel with D flag
                    tunnelUpdateInDelegatedCase(pccId, annotations, td, providerId, tunnelState, ipv4LspIdenTlv);
                }
                return;
            }
            //delegated owner will update can be a master or non-master
            if (lspObj.getDFlag() && !lspObj.getRFlag()) {
                tunnelUpdateForDelegatedLsp(tunnel, lspObj,
                        lspType, tunnelState, pccId, labelStack, ipv4LspIdenTlv);
                return;
            }
            removeOrUpdatetunnel(tunnel, lspObj, providerId, tunnelState, ipv4LspIdenTlv);
        }

        private void tunnelUpdateForDelegatedLsp(Tunnel tunnel, PcepLspObject lspObj,
                                                 LspType lspType, State tunnelState, PccId pccId,
                                                 NetworkResource labelStack,
                                                 StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv) {
            SparseAnnotations annotations = null;
            DefaultTunnelDescription td;
            boolean isPceInit = tunnel.annotations().value(PCE_INIT) == null ? false :
                    Boolean.valueOf((tunnel.annotations().value(PCE_INIT))).booleanValue();
            annotations = getAnnotations(lspObj, ipv4LspIdenTlv,
                    tunnel.annotations().value(BANDWIDTH), lspType,
                    tunnel.annotations().value(COST_TYPE), isPceInit);
            td = new DefaultTunnelDescription(null, tunnel.src(), tunnel.dst(), MPLS, new GroupId(
                    0), tunnel.providerId(), tunnel.tunnelName(),
                    tunnel.path(), labelStack, annotations);
            tunnelUpdateInDelegatedCase(pccId, annotations, td, tunnel.providerId(), tunnelState, ipv4LspIdenTlv);
        }

        private void removeOrUpdatetunnel(Tunnel tunnel, PcepLspObject lspObj, ProviderId providerId,
                State tunnelState, StatefulIPv4LspIdentifiersTlv ipv4LspIdenTlv) {
            DefaultTunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(), tunnel.src(), tunnel.dst(),
                    tunnel.type(), tunnel.groupId(), providerId, tunnel.tunnelName(), tunnel.path(),
                    (SparseAnnotations) tunnel.annotations());
            if (lspObj.getRFlag()) {
                tunnelRemoved(td);
            } else {
                PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, tunnel.path(), LSP_STATE_RPT);
                pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdenTlv);
                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                tunnelUpdated(td, tunnelState);
            }
        }

        private void tunnelUpdateInDelegatedCase(PccId pccId, SparseAnnotations annotations,
                DefaultTunnelDescription td, ProviderId providerId, State tunnelState,
                                                 StatefulIPv4LspIdentifiersTlv ipv4LspIdentifiersTlv) {
            // Wait for 2sec then query tunnel based on ingress PLSP-ID and local LSP-ID

            /*
             * If ONOS is not the master for that PCC then check if D flag is set, if yes wait [while
             * master has added the tunnel to the store] then update the tunnel.
             */
            ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();

            // Thread is started after 2 seconds first time later periodically after 2 seconds to update the tunnel
            executor.scheduleAtFixedRate(new UpdateDelegation(td, providerId, annotations, pccId,
                    executor, tunnelState, ipv4LspIdentifiersTlv), DELAY, DELAY, TimeUnit.SECONDS);
        }

        /**
         * To build Path in network from ERO object.
         *
         * @param eroObj ERO object
         * @param providerId provider id
         * @return list of links and labels
         */
        private List<Object> buildPathFromEroObj(PcepEroObject eroObj, ProviderId providerId) {
            checkNotNull(eroObj);
            List<Object> subObjList = new ArrayList<>();
            LinkedList<PcepValueType> llSubObj = eroObj.getSubObjects();
            if (llSubObj.isEmpty()) {
                log.error("ERO in report message does not have hop information");
                return new ArrayList<>();
            }
            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) {
                            Iterable<Link> links = linkService.getActiveLinks();
                            for (Link l : links) {
                                if (l.src().port().equals(PortNumber.portNumber(ipv4SubObj.getIpAddress()))) {
                                    src = l.src();
                                    isSrcSet = true;
                                    break;
                                } else if (l.dst().port().equals(PortNumber.portNumber(ipv4SubObj.getIpAddress()))) {
                                    src = l.dst();
                                    isSrcSet = true;
                                    break;
                                }
                            }
                        } else {
                            Iterable<Link> links = linkService.getActiveLinks();
                            for (Link l : links) {
                                if (l.src().port().equals(PortNumber.portNumber(ipv4SubObj.getIpAddress()))) {
                                    dst = l.src();
                                    break;
                                } else if (l.dst().port().equals(PortNumber.portNumber(ipv4SubObj.getIpAddress()))) {
                                    dst = l.dst();
                                    break;
                                }
                            }
                        Link link = DefaultLink.builder()
                                .providerId(providerId)
                                .src(src)
                                .dst(dst)
                                .type(Link.Type.DIRECT)
                                .build();
                        subObjList.add(link);
                        src = dst;
                    }
                    break;
                case SrEroSubObject.TYPE:
                    SrEroSubObject srEroSubObj = (SrEroSubObject) subObj;
                    subObjList.add(srEroSubObj.getSid());

                    if (srEroSubObj.getSt() == PcepNaiIpv4Adjacency.ST_TYPE) {
                        PcepNaiIpv4Adjacency nai = (PcepNaiIpv4Adjacency) (srEroSubObj.getNai());
                        int srcIp = nai.getLocalIpv4Addr();
                        int dstIp = nai.getRemoteIpv4Addr();
                        Iterable<Link> links = linkService.getActiveLinks();
                        for (Link l : links) {
                            long lSrc = l.src().port().toLong();
                            long lDst = l.dst().port().toLong();
                            if (lSrc == srcIp) {
                                src = l.src();
                            } else if (lDst == srcIp) {
                                src = l.dst();
                            }
                            if (lSrc == dstIp) {
                                dst = l.src();
                            } else if (lDst == dstIp) {
                                dst = l.dst();
                            }
                            if (src != null && dst != null) {
                                break;
                            }
                        }
                        if (src == null || dst == null) {
                            return new ArrayList<>();
                        }
                        Link link = DefaultLink.builder()
                                .providerId(providerId)
                                .src(src)
                                .dst(dst)
                                .type(Link.Type.DIRECT)
                                .build();
                        subObjList.add(link);
                    }
                default:
                    // the other sub objects are not required
                }
            }
            return subObjList;
        }

        @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 void handleEndOfSyncAction(Tunnel tunnel, PcepLspSyncAction endOfSyncAction) {

            if (endOfSyncAction == SEND_UPDATE) {
                updateTunnel(tunnel, tunnel.path());
                return;
            }

            TunnelDescription td = new DefaultTunnelDescription(tunnel.tunnelId(),
                                                                tunnel.src(), tunnel.dst(),
                                                                tunnel.type(),
                                                                tunnel.groupId(),
                                                                tunnel.providerId(),
                                                                tunnel.tunnelName(),
                                                                tunnel.path(),
                                                                (SparseAnnotations) tunnel.annotations());


            if (endOfSyncAction == PcepLspSyncAction.UNSTABLE) {
                // Send PCInit msg again after global reoptimization.
                tunnelUpdated(td, UNSTABLE);

                // To remove the old tunnel from store whose PLSPID is not recognized by ingress PCC.
                tunnelRemoved(td);
            } else if (endOfSyncAction == REMOVE) {
                tunnelRemoved(td);
            }
        }
    }
    @Override
    public Tunnel tunnelQueryById(TunnelId tunnelId) {
        return service.tunnelQueryById(tunnelId);
    }

    private DeviceId getDevice(PccId pccId) {
        // Get lsrId of the PCEP client from the PCC ID. Session info is based on lsrID.
        IpAddress lsrId = pccId.ipAddress();
        String lsrIdentifier = String.valueOf(lsrId);

        // Find PCC deviceID from lsrId stored as annotations
        Iterable<Device> devices = deviceService.getAvailableDevices();
        for (Device dev : devices) {
            if (dev.annotations().value(AnnotationKeys.TYPE).equals("L3")
                    && dev.annotations().value(LSRID).equals(lsrIdentifier)) {
                return dev.id();
            }
        }
        return null;
    }

    /**
     * Updates the tunnel with updated tunnel annotation after a delay of two seconds and checks it till
     * tunnel is found.
     */
    private class UpdateDelegation implements Runnable {
        DefaultTunnelDescription td;
        ProviderId providerId;
        SparseAnnotations annotations;
        PccId pccId;
        ScheduledExecutorService executor;
        State tunnelState;
        StatefulIPv4LspIdentifiersTlv ipv4LspIdentifiersTlv;

        /**
         * Creates an instance of UpdateDelegation.
         *
         * @param td tunnel description
         * @param providerId provider id
         * @param annotations tunnel annotations
         * @param pccId PCEP client id
         * @param executor service of delegated owner
         */
        public UpdateDelegation(DefaultTunnelDescription td, ProviderId providerId, SparseAnnotations annotations,
                PccId pccId, ScheduledExecutorService executor, State tunnelState,
                                StatefulIPv4LspIdentifiersTlv ipv4LspIdentifiersTlv) {
            this.td = td;
            this.providerId = providerId;
            this.annotations = annotations;
            this.pccId = pccId;
            this.executor = executor;
            this.tunnelState = tunnelState;
            this.ipv4LspIdentifiersTlv = ipv4LspIdentifiersTlv;
        }

        //Temporary using annotations later will use projection/network config service
        @Override
        public void run() {
            Collection<Tunnel> tunnelQueryResult = tunnelService.queryTunnel(td.src(), td.dst());
            TunnelId tempTunnelId = null;
            for (Tunnel t : tunnelQueryResult) {
                if (t.annotations().value(LOCAL_LSP_ID) == null ||  t.annotations().value(PLSP_ID) == null) {
                    continue;
                }

                if (t.annotations().value(LOCAL_LSP_ID).equals(td.annotations().value(LOCAL_LSP_ID))
                        && t.annotations().value(PLSP_ID).equals(td.annotations().value(PLSP_ID))
                        && ((IpTunnelEndPoint) t.src()).ip().equals(pccId.id())) {
                    tempTunnelId = t.tunnelId();
                    break;
                }
            }

            //If tunnel is found update the tunnel and shutdown the thread otherwise thread will be executing
            //periodically
            if (tempTunnelId != null) {
                Tunnel tunnel = new DefaultTunnel(providerId, td.src(), td.dst(), MPLS, new GroupId(0),
                        tempTunnelId, td.tunnelName(), td.path(), annotations);
                PcepTunnelData pcepTunnelData = new PcepTunnelData(tunnel, tunnel.path(), LSP_STATE_RPT);
                pcepTunnelData.setStatefulIpv4IndentifierTlv(ipv4LspIdentifiersTlv);
                pcepTunnelData.setLspDFlag(Boolean.valueOf(tunnel.annotations().value(DELEGATE)));
                pcepTunnelApiMapper.addToTunnelIdMap(pcepTunnelData);
                tunnelUpdated(tunnel, td.path(), tunnelState);
                executor.shutdown();
                try {
                    executor.awaitTermination(WAIT_TIME, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    log.error("updating delegation failed");
                    Thread.currentThread().interrupt();
                }
            }
        }
    }
}
