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

package org.onosproject.segmentrouting.pwaas;

import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import org.apache.commons.lang3.RandomUtils;
import org.onlab.packet.Ethernet;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DeviceId;
import org.onosproject.net.Link;
import org.onosproject.net.Path;
import org.onosproject.net.PortNumber;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flowobjective.DefaultFilteringObjective;
import org.onosproject.net.flowobjective.DefaultForwardingObjective;
import org.onosproject.net.flowobjective.DefaultNextObjective;
import org.onosproject.net.flowobjective.DefaultObjectiveContext;
import org.onosproject.net.flowobjective.FilteringObjective;
import org.onosproject.net.flowobjective.ForwardingObjective;
import org.onosproject.net.flowobjective.NextObjective;
import org.onosproject.net.flowobjective.Objective;
import org.onosproject.net.flowobjective.ObjectiveContext;
import org.onosproject.net.flowobjective.ObjectiveError;
import org.onosproject.net.topology.LinkWeigher;
import org.onosproject.segmentrouting.SRLinkWeigher;
import org.onosproject.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.store.serializers.KryoNamespaces;
import org.onosproject.store.service.ConsistentMap;
import org.onosproject.store.service.DistributedSet;
import org.onosproject.store.service.Serializer;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.INITIATION;
import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Pipeline.TERMINATION;
import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Result.*;
import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.FWD;
import static org.onosproject.segmentrouting.pwaas.L2TunnelHandler.Direction.REV;
import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;

/**
 * Handles pwaas related events.
 */
public class DefaultL2TunnelHandler implements L2TunnelHandler {

    private static final Logger log = LoggerFactory.getLogger(DefaultL2TunnelHandler.class);

    private final SegmentRoutingManager srManager;
    /**
     * To store the next objectives related to the initiation.
     */
    private final ConsistentMap<String, NextObjective> l2InitiationNextObjStore;
    /**
     * To store the next objectives related to the termination.
     */
    private final ConsistentMap<String, NextObjective> l2TerminationNextObjStore;

    /**
     * To store policies.
     */
    private final ConsistentMap<String, L2TunnelPolicy> l2PolicyStore;

    /**
     * To store tunnels.
     */
    private final ConsistentMap<String, L2Tunnel> l2TunnelStore;

    /**
     * To store pending tunnels that need to be installed.
     */
    private final ConsistentMap<String, L2Tunnel> pendingL2TunnelStore;

    /**
     * To store pending policies that need to be installed.
     */
    private final ConsistentMap<String, L2TunnelPolicy> pendingL2PolicyStore;

    private final KryoNamespace.Builder l2TunnelKryo;

    /**
     * Contains transport vlans used for spine-leaf pseudowires.
     */
    private final DistributedSet<VlanId> vlanStore;

    /**
     * Used for determining transport vlans for leaf-spine.
     */
    private short transportVlanUpper = 4093, transportVlanLower = 3500;

    private static final VlanId UNTAGGED_TRANSPORT_VLAN = VlanId.vlanId((short) 4094);

    /**
     * Create a l2 tunnel handler for the deploy and
     * for the tear down of pseudo wires.
     *
     * @param segmentRoutingManager the segment routing manager
     */
    public DefaultL2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
        srManager = segmentRoutingManager;
        l2TunnelKryo = new KryoNamespace.Builder()
                .register(KryoNamespaces.API)
                .register(L2Tunnel.class,
                          L2TunnelPolicy.class,
                          DefaultL2Tunnel.class,
                          DefaultL2TunnelPolicy.class,
                          L2Mode.class,
                          MplsLabel.class,
                          VlanId.class,
                          ConnectPoint.class);

        l2InitiationNextObjStore = srManager.
                storageService.
                <String, NextObjective>consistentMapBuilder().
                withName("onos-l2initiation-nextobj-store").
                withSerializer(Serializer.using(l2TunnelKryo.build())).
                build();

        l2TerminationNextObjStore = srManager.storageService.
                <String, NextObjective>consistentMapBuilder()
                .withName("onos-l2termination-nextobj-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

        l2PolicyStore = srManager.storageService
                .<String, L2TunnelPolicy>consistentMapBuilder()
                .withName("onos-l2-policy-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

        l2TunnelStore = srManager.storageService
                .<String, L2Tunnel>consistentMapBuilder()
                .withName("onos-l2-tunnel-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

        pendingL2PolicyStore = srManager.storageService
                .<String, L2TunnelPolicy>consistentMapBuilder()
                .withName("onos-l2-pending-policy-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

        pendingL2TunnelStore = srManager.storageService
                .<String, L2Tunnel>consistentMapBuilder()
                .withName("onos-l2-pending-tunnel-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

        vlanStore = srManager.storageService.<VlanId>setBuilder()
                .withName("onos-transport-vlan-store")
                .withSerializer(Serializer.using(
                        new KryoNamespace.Builder()
                                .register(KryoNamespaces.API)
                                .build()))
                .build()
                .asDistributedSet();
    }

    /**
     * Used by manager only in initialization.
     */
    @Override
    public void init() {
        // Since we have no pseudowires in netcfg there
        // is nothing to do in initialization.
        // I leave it here because potentially we might need to
        // use it in the future.
    }

    @Override
    public Set<L2TunnelDescription> getL2Descriptions(boolean pending) {
            // get pending tunnels/policies OR installed tunnels/policies
            List<L2Tunnel> tunnels = pending ? getL2PendingTunnels() : getL2Tunnels();
            List<L2TunnelPolicy> policies = pending ? getL2PendingPolicies() : getL2Policies();
            return tunnels.stream()
                .map(l2Tunnel -> {
                    L2TunnelPolicy policy = null;
                    for (L2TunnelPolicy l2Policy : policies) {
                        if (l2Policy.tunnelId() == l2Tunnel.tunnelId()) {
                            policy = l2Policy;
                            break;
                        }
                    }

                    return new DefaultL2TunnelDescription(l2Tunnel, policy);
                })
                .collect(Collectors.toSet());
    }

    @Override
    public List<L2TunnelPolicy> getL2Policies() {
        return new ArrayList<>(l2PolicyStore
                .values()
                .stream()
                .map(Versioned::value)
                .collect(Collectors.toList()));
    }

    @Override
    public List<L2Tunnel> getL2Tunnels() {
        return new ArrayList<>(l2TunnelStore
                .values()
                .stream()
                .map(Versioned::value)
                .collect(Collectors.toList()));
    }

    @Override
    public List<L2TunnelPolicy> getL2PendingPolicies() {
        return new ArrayList<>(pendingL2PolicyStore
                                       .values()
                                       .stream()
                                       .map(Versioned::value)
                                       .collect(Collectors.toList()));
    }

    @Override
    public List<L2Tunnel> getL2PendingTunnels() {
        return new ArrayList<>(pendingL2TunnelStore
                                       .values()
                                       .stream()
                                       .map(Versioned::value)
                                       .collect(Collectors.toList()));
    }

    @Override
    public Result verifyGlobalValidity(L2TunnelDescription pwToAdd) {

        // get both added and pending pseudowires
        List<L2TunnelDescription> newPseudowires = new ArrayList<>();
        newPseudowires.addAll(getL2Descriptions(false));
        newPseudowires.addAll(getL2Descriptions(true));
        // add the new one
        newPseudowires.add(pwToAdd);

        return configurationValidity(newPseudowires);
    }

    /**
     * Manages intermediate filtering rules.
     *
     * For leaf-spine-spine pseudowires we need to install a special filtering
     * rule in the intermediate spine for the appropriate transport vlan.
     *
     * @param pw The pseudowire, it will have the path and the transport vlan.
     */
    private Result manageIntermediateFiltering(L2TunnelDescription pw, boolean leafSpinePw) {

        // only leaf-spine-spine should need intermediate rules for now
        if (!leafSpinePw) {
            return Result.SUCCESS;
        }
        if (pw.l2Tunnel().pathUsed().size() != 2) {
            return Result.SUCCESS;
        }

        List<Link> path = pw.l2Tunnel().pathUsed();
        DeviceId intermediateSpineId = pw.l2Tunnel().pathUsed().get(0).dst().deviceId();
        L2Tunnel l2Tunnel = pw.l2Tunnel();

        log.info("Installing intermediate filtering rules for spine {} , for pseudowire {}",
                 intermediateSpineId, pw.l2Tunnel().tunnelId());

        MacAddress dstMac;
        try {
            dstMac = srManager.deviceConfiguration().getDeviceMac(intermediateSpineId);
        } catch (Exception e) {
            log.info("Device not found in configuration, no programming of MAC address");
            dstMac = null;
        }

        PortNumber inPort;

        inPort = path.get(0).dst().port();

        log.debug("Populating filtering objective for pseudowire transport" +
                         " with vlan = {}, port = {}, mac = {} for device {}",
                 l2Tunnel.transportVlan(),
                 inPort,
                 dstMac,
                 intermediateSpineId);

        FilteringObjective.Builder filteringObjectiveBuilder =
                createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
        DefaultObjectiveContext context = new DefaultObjectiveContext((objective) ->
                                                                              log.debug("Special filtObj for  " +
                                                                                                "for {} populated",
                                                                                        l2Tunnel.tunnelId()),
                                                                      (objective, error) ->
                                                                              log.warn("Failed to populate " +
                                                                                               "special filtObj " +
                                                                                               "rule for {}: {}",
                                                                                       l2Tunnel.tunnelId(), error));
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
        filteringObjectiveBuilder.withMeta(treatment.build());
        srManager.flowObjectiveService.filter(intermediateSpineId, filteringObjectiveBuilder.add(context));

        inPort = path.get(1).src().port();

        log.debug("Populating filtering objective for pseudowire transport" +
                         " with vlan = {}, port = {}, mac = {} for device {}",
                 l2Tunnel.transportVlan(),
                 inPort,
                 dstMac,
                 intermediateSpineId);

        filteringObjectiveBuilder =
                createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
        context = new DefaultObjectiveContext((objective) ->
                                                      log.debug("Special filtObj for  " + "for {} populated",
                                                                l2Tunnel.tunnelId()),
                                              (objective, error) ->
                                                      log.warn("Failed to populate " +
                                                                       "special filtObj " +
                                                                       "rule for {}: {}",
                                                               l2Tunnel.tunnelId(), error));
        treatment = DefaultTrafficTreatment.builder();
        filteringObjectiveBuilder.withMeta(treatment.build());
        srManager.flowObjectiveService.filter(intermediateSpineId, filteringObjectiveBuilder.add(context));

        return Result.SUCCESS;
    }

    /**
     * Returns the new vlan id for an ingress point of a
     * pseudowire. For double tagged, it is the outer,
     * For single tagged it is the single tag, and for
     * inner it is None.
     *
     * @param ingressOuter vlanid of ingress outer
     * @param ingressInner vlanid of ingress inner
     * @param egressOuter  vlanid of egress outer
     * @param egressInner  vlanid of egress inner
     * @return returns the vlan id which will be installed at vlan table 1.
     */
    private VlanId determineEgressVlan(VlanId ingressOuter, VlanId ingressInner,
                                      VlanId egressOuter, VlanId egressInner) {
        // validity of vlan combinations was checked at verifyPseudowire
        if (!(ingressOuter.equals(VlanId.NONE))) {
            return egressOuter;
        } else if (!(ingressInner.equals(VlanId.NONE))) {
            return egressInner;
        } else {
            return VlanId.vlanId("None");
        }
    }

    /**
     * Determines vlan used for transporting the pw traffic.
     *
     * Leaf-Leaf traffic is transferred untagged, thus we choose the UNTAGGED_TRANSPORT_VLAN
     * and also make sure to add the popVlan instruction.
     * For spine-leaf pws we choose the highest vlan value available from a certain range.
     *
     * @param spinePw if the pw is leaf-spine.
     * @return The vlan id chossen to transport this pseudowire. If vlan is UNTAGGED_TRANSPORT_VLAN
     *         then the pw is transported untagged.
     */
    private VlanId determineTransportVlan(boolean spinePw) {

        if (!spinePw) {

            log.info("Untagged transport with internal vlan {} for pseudowire!", UNTAGGED_TRANSPORT_VLAN);
            return UNTAGGED_TRANSPORT_VLAN;
        } else {
            for (short i = transportVlanUpper; i > transportVlanLower; i--) {

                VlanId vlanToUse = VlanId.vlanId(i);
                if (!vlanStore.contains(vlanToUse)) {

                    vlanStore.add(vlanToUse);
                    log.info("Transport vlan {} for pseudowire!", vlanToUse);
                    return vlanToUse;
                }
            }

            log.info("No available transport vlan found, pseudowire traffic will be carried untagged " +
                             "with internal vlan {}!", UNTAGGED_TRANSPORT_VLAN);
            return UNTAGGED_TRANSPORT_VLAN;
        }
    }

    /**
     * Returns the devices existing on a given path.
     *
     * @param path The path to traverse.
     * @return The devices on the path with the order they
     *         are traversed.
     */
    private List<DeviceId> getDevicesOnPath(List<Link> path) {

        // iterate over links and get all devices in the order
        // we find them
        List<DeviceId> deviceList = new ArrayList<DeviceId>();
        for (Link link : path) {
            if (!deviceList.contains(link.src().deviceId())) {
                deviceList.add(link.src().deviceId());
            }
            if (!deviceList.contains(link.dst().deviceId())) {
                deviceList.add(link.dst().deviceId());
            }
        }

        return deviceList;
    }

    /**
     * Returns true if path is valid according to the current logic.
     * For example : leaf to spine pseudowires can be either leaf-spine or
     * leaf-spine-spine. However, in the configuration we might specify spine device
     * first which will result in spine-spine-leaf. If leafSpinePw == true we have one of these
     * two cases and need to provision for them.
     *
     * If we have a leaf to leaf pseudowire then all the intermediate devices must
     * be spines. However, in case of paired switches we can have two leafs interconnected
     * with each other directly.
     *
     * @param path the chosen path
     * @param leafSpinePw if it is a leaf to spine pseudowire
     * @return True if path size is valid, false otherwise.
     */
    private boolean isValidPath(List<Link> path, boolean leafSpinePw) {

        List<DeviceId> devices = getDevicesOnPath(path);
        if (devices.size() < 2) {
            log.error("Path size for pseudowire should be greater than 1!");
            return false;
        }

        try {
            if (leafSpinePw) {
                // can either be leaf-spine-spine or leaf-spine
                // first device is leaf, all other must be spines
                log.debug("Devices on path are {} for leaf to spine pseudowire", devices);
                // if first device is a leaf then all other must be spines
                if (srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
                    devices.remove(0);
                    for (DeviceId devId : devices) {
                        log.debug("Device {} should be a spine!", devId);
                        if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
                            return false;
                        }
                    }
                } else {
                    // if first device is spine, last device must be a leaf
                    // all other devices must be spines
                    if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
                        return false;
                    }
                    devices.remove(devices.size() - 1);
                    for (DeviceId devId : devices) {
                        log.debug("Device {} should be a spine!", devId);
                        if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
                            return false;
                        }
                    }
                }
            } else {
                // can either be leaf-leaf (paired leafs) / leaf-spine-leaf
                // or leaf-spine-spine-leaf
                log.debug("Devices on path are {} for leaf to leaf pseudowire", devices);
                // check first device, needs to be a leaf
                if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(0))) {
                    return false;
                }
                // check last device, needs to be a leaf
                if (!srManager.deviceConfiguration().isEdgeDevice(devices.get(devices.size() - 1))) {
                    return false;
                }
                // remove these devices, rest must all be spines
                devices.remove(0);
                devices.remove(devices.size() - 1);
                for (DeviceId devId : devices) {
                    log.debug("Device {} should be a spine!", devId);
                    if (srManager.deviceConfiguration().isEdgeDevice(devId)) {
                        return false;
                    }
                }

            }
        } catch (DeviceConfigNotFoundException e) {
            log.error("Device not found in configuration : {}", e);
            return false;
        }

        return true;
    }

    /**
     * Adds a single pseudowire.
     *
     * @param pw The pseudowire to deploy
     * @return result of pseudowire deployment
     */
    public Result deployPseudowire(L2TunnelDescription pw) {

        Result result;
        long l2TunnelId;

        log.debug("Pseudowire with {} deployment started, check log for any errors in this process!",
                  pw.l2Tunnel().tunnelId());

        l2TunnelId = pw.l2Tunnel().tunnelId();
        // The tunnel id cannot be 0.
        if (l2TunnelId == 0) {
            log.warn("Tunnel id id must be > 0");
            return Result.WRONG_PARAMETERS
                    .appendError("Tunnel id id must be > 0");
        }

        result = verifyGlobalValidity(pw);
        if (result != SUCCESS) {
            log.error("Global validity for pseudowire {} is wrong!", l2TunnelId);
            return result;
        }

        // leafSpinePw determines if this is a leaf-leaf
        // or leaf-spine pseudowire
        boolean leafSpinePw;
        ConnectPoint cp1 = pw.l2TunnelPolicy().cP1();
        ConnectPoint cp2 = pw.l2TunnelPolicy().cP2();
        try {
            // differentiate between leaf-leaf pseudowires and leaf-spine
            if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
                    !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
                log.error("Can not deploy pseudowire from spine to spine!");
                return Result.WRONG_PARAMETERS
                        .appendError("Can not deploy pseudowire from spine to spine!");
            } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
                    srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
                leafSpinePw = false;
            } else {
                leafSpinePw = true;
            }
        } catch (DeviceConfigNotFoundException e) {
            log.error("Device for pseudowire connection points does not exist in the configuration");
            return Result.INTERNAL_ERROR
                    .appendError("Device for pseudowire connection points does not exist in the configuration");
        }

        // reverse the policy in order for leaf switch to be at CP1
        // this will help us for re-using SRLinkWeigher for computing valid paths
        L2TunnelPolicy reversedPolicy = reverseL2TunnelPolicy(pw.l2TunnelPolicy());
        if (reversedPolicy == null) {
            log.error("Error in reversing policy, device configuration was not found!");
            return  INTERNAL_ERROR
                    .appendError("Device configuration not found when reversing the policy.");
        }
        pw.setL2TunnelPolicy(reversedPolicy);

        // get path here, need to use the same for fwd and rev direction
        List<Link> path = getPath(pw.l2TunnelPolicy().cP1(),
                                  pw.l2TunnelPolicy().cP2());
        if (path == null) {
            log.error("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
            return PATH_NOT_FOUND.appendError("No path between the connection points for pseudowire!");
        }

        Link fwdNextHop;
        Link revNextHop;
        if (!isValidPath(path, leafSpinePw)) {
            log.error("Deploying process : Path for pseudowire {} is not valid",
                      l2TunnelId);
            return INTERNAL_ERROR.appendError("Internal error : path for pseudowire is not valid!");
        }

        // oneHope flag is used to determine if we need to
        // install transit mpls rules
        boolean oneHop = true;
        if (path.size() > 1) {
            oneHop = false;
        }

        fwdNextHop = path.get(0);
        revNextHop = reverseLink(path.get(path.size() - 1));

        pw.l2Tunnel().setPath(path);
        pw.l2Tunnel().setTransportVlan(determineTransportVlan(leafSpinePw));

        // next hops for next objectives
        log.info("Deploying process : Establishing forward direction for pseudowire {}", l2TunnelId);

        VlanId egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP1OuterTag(),
                                                pw.l2TunnelPolicy().cP1InnerTag(),
                                                pw.l2TunnelPolicy().cP2OuterTag(),
                                                pw.l2TunnelPolicy().cP2InnerTag());
        // We establish the tunnel.
        // result.nextId will be used in fwd
        result = deployPseudoWireInit(pw.l2Tunnel(),
                                      pw.l2TunnelPolicy().cP1(),
                                      pw.l2TunnelPolicy().cP2(),
                                      FWD,
                                      fwdNextHop,
                                      leafSpinePw,
                                      oneHop,
                                      egressVlan);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
            return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire initiation for CP1");
        }

        // We create the policy.
        result = deployPolicy(l2TunnelId,
                              pw.l2TunnelPolicy().cP1(),
                              pw.l2TunnelPolicy().cP1InnerTag(),
                              pw.l2TunnelPolicy().cP1OuterTag(),
                              egressVlan,
                              result.getNextId());
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire policy for CP1");
            return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire policy for CP1");
        }

        // We terminate the tunnel
        result = deployPseudoWireTerm(pw.l2Tunnel(),
                                       pw.l2TunnelPolicy().cP2(),
                                       egressVlan,
                                       FWD,
                                       leafSpinePw,
                                       oneHop);

        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire termination for CP1");
            return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP1");
        }

        log.info("Deploying process : Establishing reverse direction for pseudowire {}", l2TunnelId);

        egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
                                         pw.l2TunnelPolicy().cP2InnerTag(),
                                         pw.l2TunnelPolicy().cP1OuterTag(),
                                         pw.l2TunnelPolicy().cP1InnerTag());

        // We establish the reverse tunnel.
        result = deployPseudoWireInit(pw.l2Tunnel(),
                                       pw.l2TunnelPolicy().cP2(),
                                       pw.l2TunnelPolicy().cP1(),
                                       REV,
                                       revNextHop,
                                       leafSpinePw,
                                       oneHop,
                                       egressVlan);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire initiation for CP2");
            return Result.INTERNAL_ERROR
                    .appendError("Error in deploying pseudowire initiation for CP2");
        }


        result = deployPolicy(l2TunnelId,
                               pw.l2TunnelPolicy().cP2(),
                               pw.l2TunnelPolicy().cP2InnerTag(),
                               pw.l2TunnelPolicy().cP2OuterTag(),
                               egressVlan,
                               result.getNextId());
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying policy for CP2");
            return Result.INTERNAL_ERROR
                    .appendError("Deploying process : Error in deploying policy for CP2");
        }

        result = deployPseudoWireTerm(pw.l2Tunnel(),
                                      pw.l2TunnelPolicy().cP1(),
                                      egressVlan,
                                      REV,
                                      leafSpinePw,
                                      oneHop);

        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire termination for CP2");
            return Result.INTERNAL_ERROR.appendError("Error in deploying pseudowire termination for CP2");
        }

        result = manageIntermediateFiltering(pw, leafSpinePw);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in installing intermediate rules for tagged transport");
            return Result.INTERNAL_ERROR.appendError("Error in installing intermediate rules for tagged transport");
        }

        log.info("Deploying process : Updating relevant information for pseudowire {}", l2TunnelId);

        // Populate stores as the final step of the process
        l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
        l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());

        return Result.SUCCESS;
    }

    @Override
    public Result checkIfPwExists(long tunnelId, boolean pending) {

        List<L2TunnelDescription> pseudowires = getL2Descriptions(pending)
                .stream()
                .filter(pw -> pw.l2Tunnel().tunnelId() == tunnelId)
                .collect(Collectors.toList());

        if (pseudowires.size() == 0) {
            String store = ((pending) ? "pending" : "installed");
            log.error("Pseudowire {} does not exist in {} store", tunnelId, store);
            return Result.WRONG_PARAMETERS.
                    appendError("Pseudowire " + tunnelId + " does not exist in " + store);
        } else {
            return SUCCESS;
        }
    }

    /**
     * Tears down connection points of pseudowires. We can either tear down both connection points,
     * or each one of them.
     *
     * @param l2TunnelId The tunnel id for this pseudowire.
     * @param tearDownFirst Boolean, true if we want to tear down cp1
     * @param tearDownSecond Boolean, true if we want to tear down cp2
     * @param pending Boolean, if true remove only pseudowire from pending stores since no flows/groups
     *                in the network, else remove flows/groups in the devices also.
     * @return Result of tearing down the pseudowire, SUCCESS if everything was ok
     *         a descriptive error otherwise.
     */
    private Result tearDownConnectionPoints(long l2TunnelId, boolean tearDownFirst,
                                            boolean tearDownSecond, boolean pending) {

        Result res;
        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();

        if (l2TunnelId == 0) {
            log.warn("Removal process : Tunnel id cannot be 0");
            return Result.WRONG_PARAMETERS.appendError("Pseudowire id can not be 0.");
        }

        res = checkIfPwExists(l2TunnelId, pending);
        if (res != Result.SUCCESS) {
            return res;
        }

        // remove and get the tunnel and the policy from the appropriate store
        // if null, return error.
        Versioned<L2Tunnel> l2TunnelVersioned = pending ?
                pendingL2TunnelStore.remove(Long.toString(l2TunnelId)) :
                l2TunnelStore.remove(Long.toString(l2TunnelId));
        Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = pending ?
                pendingL2PolicyStore.remove(Long.toString(l2TunnelId)) :
                l2PolicyStore.remove(Long.toString(l2TunnelId));
        if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
            log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
            return Result.INTERNAL_ERROR
                    .appendError("Policy and/or tunnel missing for pseudowire!");
        }

        L2TunnelDescription pwToRemove = new DefaultL2TunnelDescription(l2TunnelVersioned.value(),
                                                                        l2TunnelPolicyVersioned.value());

        // remove the reserved transport vlan
        if (!pwToRemove.l2Tunnel().transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {
            vlanStore.remove(pwToRemove.l2Tunnel().transportVlan());
        }

        if (pending) {
            // no need to remove flows / groups for a pseudowire
            // in pending state
            return Result.SUCCESS;
        }

        // remove flows/groups involving with this pseudowire
        if (tearDownFirst) {
            log.info("Removal process : Tearing down forward direction of pseudowire {}", l2TunnelId);

            VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP1OuterTag(),
                                                    pwToRemove.l2TunnelPolicy().cP1InnerTag(),
                                                    pwToRemove.l2TunnelPolicy().cP2OuterTag(),
                                                    pwToRemove.l2TunnelPolicy().cP2InnerTag());
            deletePolicy(l2TunnelId,
                         pwToRemove.l2TunnelPolicy().cP1(),
                         pwToRemove.l2TunnelPolicy().cP1InnerTag(),
                         pwToRemove.l2TunnelPolicy().cP1OuterTag(),
                         egressVlan,
                         fwdInitNextFuture,
                         FWD);

            fwdInitNextFuture.thenAcceptAsync(status -> {
                if (status == null) {
                    // Finally we will tear down the pseudo wire.
                    tearDownPseudoWireInit(l2TunnelId,
                                           pwToRemove.l2TunnelPolicy().cP1(),
                                           fwdTermNextFuture,
                                           FWD);
                }
            });

            fwdTermNextFuture.thenAcceptAsync(status -> {
                if (status == null) {
                    tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
                                           pwToRemove.l2TunnelPolicy().cP2(),
                                           null,
                                           FWD);
                }
            });
        }

        if (tearDownSecond) {
            log.info("Removal process : Tearing down reverse direction of pseudowire {}", l2TunnelId);

            VlanId egressVlan = determineEgressVlan(pwToRemove.l2TunnelPolicy().cP2OuterTag(),
                                             pwToRemove.l2TunnelPolicy().cP2InnerTag(),
                                             pwToRemove.l2TunnelPolicy().cP1OuterTag(),
                                             pwToRemove.l2TunnelPolicy().cP1InnerTag());

            // We do the same operations on the reverse side.
            deletePolicy(l2TunnelId,
                         pwToRemove.l2TunnelPolicy().cP2(),
                         pwToRemove.l2TunnelPolicy().cP2InnerTag(),
                         pwToRemove.l2TunnelPolicy().cP2OuterTag(),
                         egressVlan,
                         revInitNextFuture,
                         REV);

            revInitNextFuture.thenAcceptAsync(status -> {
                if (status == null) {
                    tearDownPseudoWireInit(l2TunnelId,
                                           pwToRemove.l2TunnelPolicy().cP2(),
                                           revTermNextFuture,
                                           REV);
                }
            });

            revTermNextFuture.thenAcceptAsync(status -> {
                if (status == null) {
                    tearDownPseudoWireTerm(pwToRemove.l2Tunnel(),
                                           pwToRemove.l2TunnelPolicy().cP1(),
                                           null,
                                           REV);
                }
            });
        }

        return Result.SUCCESS;
    }

    /**
     * Helper function for removing a single pseudowire.
     *
     * Tries to remove pseudowire from any store it might reside (pending or installed).
     *
     * @param l2TunnelId the id of the pseudowire to tear down
     * @return Returns SUCCESS if no error is obeserved or an appropriate
     * error on a failure
     */
    public Result tearDownPseudowire(long l2TunnelId) {

        if (checkIfPwExists(l2TunnelId, true) == Result.SUCCESS) {
            return tearDownConnectionPoints(l2TunnelId, true, true, true);
        } else if (checkIfPwExists(l2TunnelId, false) == Result.SUCCESS) {
            return tearDownConnectionPoints(l2TunnelId, true, true, false);
        } else {
            return Result.WRONG_PARAMETERS.appendError("Pseudowire with "
                                                        + l2TunnelId
                                                        + " did not reside in any store!");
        }
    }

    @Deprecated
    public void tearDown(Set<L2TunnelDescription> pwToRemove) {

        for (L2TunnelDescription currentL2Tunnel : pwToRemove) {

            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();
            log.info("Removing pseudowire {}", tunnelId);

            Result result = tearDownPseudowire(tunnelId);
            if (result != Result.SUCCESS) {
                log.error("Could not remove pseudowire {}!", tunnelId);
            }
        }
    }

    /**
     * Handles the policy establishment which consists in
     * create the filtering and forwarding objectives related
     * to the initiation and termination.
     *
     * @param tunnelId     the tunnel id
     * @param ingress      the ingress point
     * @param ingressInner the ingress inner tag
     * @param ingressOuter the ingress outer tag
     * @param nextId       the next objective id
     * @param egressVlan   Vlan-id to set, depends on ingress vlan
     *                     combinations. For example, if pw is double tagged
     *                     then this is the value of the outer vlan, if single
     *                     tagged then it is the new value of the single tag.
     *                     Should be None for untagged traffic.
     * @return the result of the operation
     */
    private Result deployPolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner,
                                VlanId ingressOuter, VlanId egressVlan, int nextId) {

        List<Objective> objectives = Lists.newArrayList();
        // We create the forwarding objective for supporting
        // the l2 tunnel.
        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
        // We create and add objective context.
        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
                                                                log.debug("FwdObj for tunnel {} populated", tunnelId),
                                                               (objective, error) ->
                                                                log.warn("Failed to populate fwdrObj " +
                                                                                 "for tunnel {}", tunnelId, error));
        objectives.add(fwdBuilder.add(context));

        // We create the filtering objective to define the
        // permit traffic in the switch
        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);

        // We add the metadata.
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
                .builder()
                .setTunnelId(tunnelId)
                .setVlanId(egressVlan);
        filtBuilder.withMeta(treatment.build());

        // We create and add objective context.
        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for tunnel {} populated", tunnelId),
                                              (objective, error) -> log.warn("Failed to populate filterObj for " +
                                                                                     "tunnel {}", tunnelId, error));
        objectives.add(filtBuilder.add(context));

        for (Objective objective : objectives) {
            if (objective instanceof ForwardingObjective) {
                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
                log.debug("Creating new FwdObj for initiation NextObj with id={} for tunnel {}", nextId, tunnelId);
            } else {
                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
                log.debug("Creating new FiltObj for tunnel {}", tunnelId);
            }
        }
        return SUCCESS;
    }

    /**
     * Handles the tunnel establishment which consists in
     * create the next objectives related to the initiation.
     *
     * @param l2Tunnel  the tunnel to deploy
     * @param ingress   the ingress connect point
     * @param egress    the egress connect point
     * @param direction the direction of the pw
     * @param spinePw if the pseudowire involves a spine switch
     * @return the result of the operation
     */
    private Result deployPseudoWireInit(L2Tunnel l2Tunnel, ConnectPoint ingress,
                                        ConnectPoint egress, Direction direction,
                                        Link nextHop, boolean spinePw, boolean oneHop, VlanId termVlanId) {

        if (nextHop == null) {
            log.warn("No path between ingress and egress cps for tunnel {}", l2Tunnel.tunnelId());
            return WRONG_PARAMETERS;
        }

        // We create the next objective without the metadata
        // context and id. We check if it already exists in the
        // store. If not we store as it is in the store.
        NextObjective.Builder nextObjectiveBuilder = createNextObjective(INITIATION,
                                                                         nextHop.src(),
                                                                         nextHop.dst(),
                                                                         l2Tunnel,
                                                                         egress.deviceId(),
                                                                         spinePw,
                                                                         oneHop,
                                                                         termVlanId);

        if (nextObjectiveBuilder == null) {
            return INTERNAL_ERROR;
        }
        // We set the metadata. We will use this metadata
        // to inform the driver we are doing a l2 tunnel.
        TrafficSelector metadata = DefaultTrafficSelector
                .builder()
                .matchTunnelId(l2Tunnel.tunnelId())
                .build();
        nextObjectiveBuilder.withMeta(metadata);
        int nextId = srManager.flowObjectiveService.allocateNextId();
        if (nextId < 0) {
            log.warn("Not able to allocate a next id for initiation");
            return INTERNAL_ERROR;
        }
        nextObjectiveBuilder.withId(nextId);
        String key = generateKey(l2Tunnel.tunnelId(), direction);
        l2InitiationNextObjStore.put(key, nextObjectiveBuilder.add());
        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
                                                                 log.debug("Initiation l2 tunnel rule " +
                                                                                   "for {} populated",
                                                                           l2Tunnel.tunnelId()),
                                                               (objective, error) ->
                                                                       log.warn("Failed to populate Initiation " +
                                                                                        "l2 tunnel rule for {}: {}",
                                                                                l2Tunnel.tunnelId(), error));
        NextObjective nextObjective = nextObjectiveBuilder.add(context);
        srManager.flowObjectiveService.next(ingress.deviceId(), nextObjective);
        log.debug("Initiation next objective for {} not found. Creating new NextObj with id={}",
                  l2Tunnel.tunnelId(), nextObjective.id());
        Result result = SUCCESS;
        result.setNextId(nextObjective.id());
        return result;
    }

    /**
     * Handles the tunnel termination, which consists in the creation
     * of a forwarding objective and a next objective.
     *
     * @param l2Tunnel   the tunnel to terminate
     * @param egress     the egress point
     * @param egressVlan the expected vlan at egress
     * @param direction  the direction
     * @param spinePw if the pseudowire involves a spine switch
     * @return the result of the operation
     */
    private Result deployPseudoWireTerm(L2Tunnel l2Tunnel, ConnectPoint egress,
                                        VlanId egressVlan, Direction direction, boolean spinePw, boolean oneHop) {

        // We create the group relative to the termination.
        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
                                                                         l2Tunnel, egress.deviceId(),
                                                                         spinePw,
                                                                         oneHop,
                                                                         egressVlan);
        if (nextObjectiveBuilder == null) {
            return INTERNAL_ERROR;
        }
        TrafficSelector metadata = DefaultTrafficSelector
                .builder()
                .matchVlanId(egressVlan)
                .build();
        nextObjectiveBuilder.withMeta(metadata);
        int nextId = srManager.flowObjectiveService.allocateNextId();
        if (nextId < 0) {
            log.warn("Not able to allocate a next id for initiation");
            return INTERNAL_ERROR;
        }
        nextObjectiveBuilder.withId(nextId);
        String key = generateKey(l2Tunnel.tunnelId(), direction);
        l2TerminationNextObjStore.put(key, nextObjectiveBuilder.add());
        ObjectiveContext context = new DefaultObjectiveContext((objective) -> log.debug("Termination l2 tunnel rule " +
                                                                                        "for {} populated",
                                                                                        l2Tunnel.tunnelId()),
                                                               (objective, error) -> log.warn("Failed to populate " +
                                                                                              "termination l2 tunnel " +
                                                                                              "rule for {}: {}",
                                                                                              l2Tunnel.tunnelId(),
                                                                                              error));
        NextObjective nextObjective = nextObjectiveBuilder.add(context);
        srManager.flowObjectiveService.next(egress.deviceId(), nextObjective);
        log.debug("Termination next objective for {} not found. Creating new NextObj with id={}",
                  l2Tunnel.tunnelId(), nextObjective.id());

        // We create the flow relative to the termination.
        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(), l2Tunnel.tunnelId(),
                                                                        egress.port(), nextObjective.id());
        context = new DefaultObjectiveContext((objective) -> log.debug("FwdObj for tunnel termination {} populated",
                                                                       l2Tunnel.tunnelId()),
                                              (objective, error) -> log.warn("Failed to populate fwdrObj" +
                                                                             " for tunnel termination {}",
                                                                             l2Tunnel.tunnelId(), error));
        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.add(context));
        log.debug("Creating new FwdObj for termination NextObj with id={} for tunnel {}",
                  nextId, l2Tunnel.tunnelId());

        if (spinePw) {

            // determine the input port at the
            PortNumber inPort;

            if (egress.deviceId().
                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
                    inPort = l2Tunnel.pathUsed().get(0).dst().port();
            } else {
                    inPort = l2Tunnel.pathUsed().get(0).src().port();
            }

            MacAddress dstMac;
            try {
                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
            } catch (Exception e) {
                log.info("Device not found in configuration, no programming of MAC address");
                dstMac = null;
            }

            log.info("Populating filtering objective for pseudowire transport" +
                             " with vlan = {}, port = {}, mac = {}",
                     l2Tunnel.transportVlan(),
                     inPort,
                     dstMac);
            FilteringObjective.Builder filteringObjectiveBuilder =
                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
            context = new DefaultObjectiveContext(( objective ) ->
                                                          log.debug("Special filtObj for  " + "for {} populated",
                                                                    l2Tunnel.tunnelId()),
                                                  ( objective, error ) ->
                                                          log.warn("Failed to populate " +
                                                                           "special filtObj " +
                                                                           "rule for {}: {}",
                                                                                   l2Tunnel.tunnelId(), error));
            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
            filteringObjectiveBuilder.withMeta(treatment.build());
            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.add(context));
            log.debug("Creating new special FiltObj for termination point with tunnel {} for port {}",
                      l2Tunnel.tunnelId(),
                      inPort);
        }

        return SUCCESS;
    }


    /**
     * Creates the filtering objective according to a given port and vlanid.
     *
     * @param inPort   the in port
     * @param vlanId the inner vlan tag
     * @return the filtering objective
     */
    private FilteringObjective.Builder createNormalPipelineFiltObjective(PortNumber inPort,
                                                                         VlanId vlanId,
                                                                         MacAddress dstMac) {

        log.info("Creating filtering objective for pseudowire transport with vlan={}, port={}, mac={}",
                 vlanId,
                 inPort,
                 dstMac);
        FilteringObjective.Builder fwdBuilder = DefaultFilteringObjective
                .builder()
                .withKey(Criteria.matchInPort(inPort))
                .addCondition(Criteria.matchVlanId(vlanId))
                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
                .permit()
                .fromApp(srManager.appId());

        if (dstMac != null) {
            fwdBuilder.addCondition(Criteria.matchEthDst(dstMac));
        }

        return fwdBuilder;
    }

    /**
     * Creates the filtering objective according to a given policy.
     *
     * @param inPort   the in port
     * @param innerTag the inner vlan tag
     * @param outerTag the outer vlan tag
     * @return the filtering objective
     */
    private FilteringObjective.Builder createFiltObjective(PortNumber inPort, VlanId innerTag, VlanId outerTag) {

        log.info("Creating filtering objective for vlans {} / {}", outerTag, innerTag);
        return DefaultFilteringObjective
                .builder()
                .withKey(Criteria.matchInPort(inPort))
                .addCondition(Criteria.matchInnerVlanId(innerTag))
                .addCondition(Criteria.matchVlanId(outerTag))
                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
                .permit()
                .fromApp(srManager.appId());
    }

    /**
     * Creates the forwarding objective for the termination.
     *
     * @param pwLabel    the pseudo wire label
     * @param tunnelId   the tunnel id
     * @param egressPort the egress port
     * @param nextId     the next step
     * @return the forwarding objective to support the termination
     */
    private ForwardingObjective.Builder createTermFwdObjective(MplsLabel pwLabel, long tunnelId,
                                                               PortNumber egressPort, int nextId) {

        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();
        TrafficTreatment.Builder trafficTreatment = DefaultTrafficTreatment.builder();
        // The flow has to match on the pw label and bos
        trafficSelector.matchEthType(Ethernet.MPLS_UNICAST);
        trafficSelector.matchMplsLabel(pwLabel);
        trafficSelector.matchMplsBos(true);
        // The flow has to decrement ttl, restore ttl in
        // pop mpls, set tunnel id and port.
        trafficTreatment.decMplsTtl();
        trafficTreatment.copyTtlIn();
        trafficTreatment.popMpls();
        trafficTreatment.setTunnelId(tunnelId);
        trafficTreatment.setOutput(egressPort);

        return DefaultForwardingObjective
                .builder()
                .fromApp(srManager.appId())
                .makePermanent()
                .nextStep(nextId)
                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
                .withSelector(trafficSelector.build())
                .withTreatment(trafficTreatment.build())
                .withFlag(VERSATILE);
    }

    /**
     * Creates the forwarding objective for the initiation.
     *
     * @param tunnelId the tunnel id
     * @param inPort   the input port
     * @param nextId   the next step
     * @return the forwarding objective to support the initiation.
     */
    private ForwardingObjective.Builder createInitFwdObjective(long tunnelId, PortNumber inPort, int nextId) {

        TrafficSelector.Builder trafficSelector = DefaultTrafficSelector.builder();

        // The flow has to match on the mpls logical
        // port and the tunnel id.
        trafficSelector.matchTunnelId(tunnelId);
        trafficSelector.matchInPort(inPort);

        return DefaultForwardingObjective
                .builder()
                .fromApp(srManager.appId())
                .makePermanent()
                .nextStep(nextId)
                .withPriority(SegmentRoutingService.DEFAULT_PRIORITY)
                .withSelector(trafficSelector.build())
                .withFlag(VERSATILE);

    }

    /**
     * Creates the next objective according to a given
     * pipeline. We don't set the next id and we don't
     * create the final meta to check if we are re-using
     * the same next objective for different tunnels.
     *
     * @param pipeline the pipeline to support
     * @param srcCp    the source port
     * @param dstCp    the destination port
     * @param l2Tunnel the tunnel to support
     * @param egressId the egress device id
     * @param oneHop if the pw only has one hop, push only pw label
     * @param leafSpinePw true if we want instantiate a leaf-spine or leaf-spine-spine pw
     * @param termVlanId the outer vlan id of the packet exiting a termination point
     * @return the next objective to support the pipeline
     */
    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
                                                      ConnectPoint dstCp,  L2Tunnel l2Tunnel,
                                                      DeviceId egressId, boolean leafSpinePw,
                                                      boolean oneHop, VlanId termVlanId) {
        NextObjective.Builder nextObjBuilder;
        TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
        if (pipeline == INITIATION) {
            nextObjBuilder = DefaultNextObjective
                    .builder()
                    .withType(NextObjective.Type.SIMPLE)
                    .fromApp(srManager.appId());
            // The pw label is the bottom of stack. It has to
            // be different -1.
            if (l2Tunnel.pwLabel().toInt() == MplsLabel.MAX_MPLS) {
                log.warn("Pw label not configured");
                return null;
            }
            treatmentBuilder.pushMpls();
            treatmentBuilder.setMpls(l2Tunnel.pwLabel());
            treatmentBuilder.setMplsBos(true);
            treatmentBuilder.copyTtlOut();

            // If the inter-co label is present we have to set the label.
            if (l2Tunnel.interCoLabel().toInt() != MplsLabel.MAX_MPLS) {
                treatmentBuilder.pushMpls();
                treatmentBuilder.setMpls(l2Tunnel.interCoLabel());
                treatmentBuilder.setMplsBos(false);
                treatmentBuilder.copyTtlOut();
            }

            // if not oneHop install transit mpls labels also
            if (!oneHop) {
                // We retrieve the sr label from the config
                // specific for pseudowire traffic
                // using the egress leaf device id.
                MplsLabel srLabel;
                try {
                    srLabel = MplsLabel.mplsLabel(srManager.deviceConfiguration().getPWRoutingLabel(egressId));

                } catch (DeviceConfigNotFoundException e) {
                    log.warn("Sr label for pw traffic not configured");
                    return null;
                }

                treatmentBuilder.pushMpls();
                treatmentBuilder.setMpls(srLabel);
                treatmentBuilder.setMplsBos(false);
                treatmentBuilder.copyTtlOut();
            }

            // We have to rewrite the src and dst mac address.
            MacAddress ingressMac;
            try {
                ingressMac = srManager.deviceConfiguration().getDeviceMac(srcCp.deviceId());
            } catch (DeviceConfigNotFoundException e) {
                log.warn("Was not able to find the ingress mac");
                return null;
            }
            treatmentBuilder.setEthSrc(ingressMac);
            MacAddress neighborMac;
            try {
                neighborMac = srManager.deviceConfiguration().getDeviceMac(dstCp.deviceId());
            } catch (DeviceConfigNotFoundException e) {
                log.warn("Was not able to find the neighbor mac");
                return null;
            }
            treatmentBuilder.setEthDst(neighborMac);

            // if true we need to pop the vlan because
            // we instantiate a leaf to leaf pseudowire
            if (!leafSpinePw) {
                log.info("We should carry this traffic UNTAGGED!");
                treatmentBuilder.popVlan();
            }

            // set the appropriate transport vlan from tunnel information
            treatmentBuilder.setVlanId(l2Tunnel.transportVlan());
        } else {
            // We create the next objective which
            // will be a simple l2 group.
            nextObjBuilder = DefaultNextObjective
                    .builder()
                    .withType(NextObjective.Type.SIMPLE)
                    .fromApp(srManager.appId());

            // for termination point we use the outer vlan of the
            // encapsulated packet
            treatmentBuilder.setVlanId(termVlanId);
        }

        treatmentBuilder.setOutput(srcCp.port());
        nextObjBuilder.addTreatment(treatmentBuilder.build());
        return nextObjBuilder;
    }

    /**
     * Reverse an l2 tunnel policy in order to have as CP1 the leaf switch,
     * in case one of the switches is a spine.
     *
     * This makes possible the usage of SRLinkWeigher for computing valid paths,
     * which cuts leaf-spine links from the path computation with a src different
     * than the source leaf.
     *
     * @param policy The policy to reverse, if needed
     * @return a l2TunnelPolicy containing the leaf at CP1, suitable for usage with
     *         current SRLinkWeigher
     */
    private L2TunnelPolicy reverseL2TunnelPolicy(L2TunnelPolicy policy) {
        try {
            // if cp1 is a leaf, just return
            if (srManager.deviceConfiguration().isEdgeDevice(policy.cP1().deviceId())) {
                return policy;
            } else {
                // return a policy with reversed cp1 and cp2, and also with reversed tags
                return new DefaultL2TunnelPolicy(policy.tunnelId(),
                                                 policy.cP2(), policy.cP2InnerTag(), policy.cP2OuterTag(),
                                                 policy.cP1(), policy.cP1InnerTag(), policy.cP1OuterTag());

            }
        } catch (DeviceConfigNotFoundException e) {
            // should never come here, since it has been checked before
            log.error("Configuration for device {}, does not exist!");
            return null;
        }
    }

    /**
     * Reverses a link.
     *
     * @param link link to be reversed
     * @return the reversed link
     */
    private Link reverseLink(Link link) {

        DefaultLink.Builder linkBuilder = DefaultLink.builder();

        linkBuilder.src(link.dst());
        linkBuilder.dst(link.src());
        linkBuilder.type(link.type());
        linkBuilder.providerId(link.providerId());

        return linkBuilder.build();
    }

    /**
     * Returns the path betwwen two connect points.
     *
     * @param srcCp source connect point
     * @param dstCp destination connect point
     * @return the path
     */
    private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {

        // use SRLinkWeigher to avoid pair links, and also
        // avoid going from the spine to the leaf and to the
        // spine again, we need to have the leaf as CP1 here.
        LinkWeigher srLw = new SRLinkWeigher(srManager, srcCp.deviceId(), new HashSet<Link>());

        Set<Path> paths = srManager.topologyService.
                getPaths(srManager.topologyService.currentTopology(),
                srcCp.deviceId(), dstCp.deviceId(), srLw);

        log.debug("Paths obtained from topology service {}", paths);

        // We randomly pick a path.
        if (paths.isEmpty()) {
            return null;
        }
        int size = paths.size();
        int index = RandomUtils.nextInt(0, size);

        List<Link> result = Iterables.get(paths, index).links();
        log.debug("Randomly picked a path {}", result);

        return result;
    }

    /**
     * Deletes a given policy using the parameter supplied.
     *
     * @param tunnelId     the tunnel id
     * @param ingress      the ingress point
     * @param ingressInner the ingress inner vlan id
     * @param ingressOuter the ingress outer vlan id
     * @param future       to perform the async operation
     * @param direction    the direction: forward or reverse
     */
    private void deletePolicy(long tunnelId, ConnectPoint ingress, VlanId ingressInner, VlanId ingressOuter,
                              VlanId egressVlan, CompletableFuture<ObjectiveError> future, Direction direction) {

        String key = generateKey(tunnelId, direction);
        if (!l2InitiationNextObjStore.containsKey(key)) {
            log.warn("Abort delete of policy for tunnel {}: next does not exist in the store", tunnelId);
            if (future != null) {
                future.complete(null);
            }
            return;
        }
        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
        int nextId = nextObjective.id();
        List<Objective> objectives = Lists.newArrayList();
        // We create the forwarding objective.
        ForwardingObjective.Builder fwdBuilder = createInitFwdObjective(tunnelId, ingress.port(), nextId);
        ObjectiveContext context = new ObjectiveContext() {
            @Override
            public void onSuccess(Objective objective) {
                log.debug("Previous fwdObj for policy {} removed", tunnelId);
                if (future != null) {
                    future.complete(null);
                }
            }

            @Override
            public void onError(Objective objective, ObjectiveError error) {
                log.warn("Failed to remove previous fwdObj for policy {}: {}", tunnelId, error);
                if (future != null) {
                    future.complete(error);
                }
            }
        };
        objectives.add(fwdBuilder.remove(context));
        // We create the filtering objective to define the
        // permit traffic in the switch
        FilteringObjective.Builder filtBuilder = createFiltObjective(ingress.port(), ingressInner, ingressOuter);
        TrafficTreatment.Builder treatment = DefaultTrafficTreatment
                .builder()
                .setTunnelId(tunnelId)
                .setVlanId(egressVlan);
        filtBuilder.withMeta(treatment.build());
        context = new DefaultObjectiveContext((objective) -> log.debug("FilterObj for policy {} revoked", tunnelId),
                                              (objective, error) ->
                                                      log.warn("Failed to revoke filterObj for policy {}",
                                                               tunnelId, error));
        objectives.add(filtBuilder.remove(context));

        for (Objective objective : objectives) {
            if (objective instanceof ForwardingObjective) {
                srManager.flowObjectiveService.forward(ingress.deviceId(), (ForwardingObjective) objective);
            } else {
                srManager.flowObjectiveService.filter(ingress.deviceId(), (FilteringObjective) objective);
            }
        }
    }

    /**
     * Deletes the pseudo wire initiation.
     *
     * @param l2TunnelId the tunnel id
     * @param ingress    the ingress connect point
     * @param future     to perform an async operation
     * @param direction  the direction: reverse of forward
     */
    private void tearDownPseudoWireInit(long l2TunnelId, ConnectPoint ingress,
                                        CompletableFuture<ObjectiveError> future, Direction direction) {

        String key = generateKey(l2TunnelId, direction);
        if (!l2InitiationNextObjStore.containsKey(key)) {
            log.info("Abort delete of {} for {}: next does not exist in the store", INITIATION, key);
            if (future != null) {
                future.complete(null);
            }
            return;
        }

        // un-comment in case you want to delete groups used by the pw
        // however, this will break the update of pseudowires cause the L2 interface group can
        // not be deleted (it is referenced by other groups)
        /*
        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();
        ObjectiveContext context = new ObjectiveContext() {
            @Override
            public void onSuccess(Objective objective) {
                log.debug("Previous {} next for {} removed", INITIATION, key);
                if (future != null) {
                    future.complete(null);
                }
            }

            @Override
            public void onError(Objective objective, ObjectiveError error) {
                log.warn("Failed to remove previous {} next for {}: {}", INITIATION, key, error);
                if (future != null) {
                    future.complete(error);
                }
            }
        };
        srManager.flowObjectiveService.next(ingress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
        */

        future.complete(null);
        l2InitiationNextObjStore.remove(key);
    }

    /**
     * Deletes the pseudo wire termination.
     *
     * @param l2Tunnel  the tunnel
     * @param egress    the egress connect point
     * @param future    the async task
     * @param direction the direction of the tunnel
     */
    private void tearDownPseudoWireTerm(L2Tunnel l2Tunnel,
                                        ConnectPoint egress,
                                        CompletableFuture<ObjectiveError> future,
                                        Direction direction) {

        String key = generateKey(l2Tunnel.tunnelId(), direction);
        if (!l2TerminationNextObjStore.containsKey(key)) {
            log.info("Abort delete of {} for {}: next does not exist in the store", TERMINATION, key);
            if (future != null) {
                future.complete(null);
            }
            return;
        }
        NextObjective nextObjective = l2TerminationNextObjStore.get(key).value();
        ForwardingObjective.Builder fwdBuilder = createTermFwdObjective(l2Tunnel.pwLabel(),
                                                                        l2Tunnel.tunnelId(),
                                                                        egress.port(),
                                                                        nextObjective.id());
        ObjectiveContext context = new DefaultObjectiveContext((objective) ->
                                                                       log.debug("FwdObj for {} {}, " +
                                                                                         "direction {} removed",
                                                                                        TERMINATION,
                                                                                        l2Tunnel.tunnelId(),
                                                                                        direction),
                                                               (objective, error) ->
                                                                       log.warn("Failed to remove fwdObj " +
                                                                                        "for {} {}" +
                                                                                        ", direction {}",
                                                                                TERMINATION,
                                                                                l2Tunnel.tunnelId(),
                                                                                error,
                                                                                direction));
        srManager.flowObjectiveService.forward(egress.deviceId(), fwdBuilder.remove(context));

        // un-comment in case you want to delete groups used by the pw
        // however, this will break the update of pseudowires cause the L2 interface group can
        // not be deleted (it is referenced by other groups)
        /*
        context = new ObjectiveContext() {
            @Override
            public void onSuccess(Objective objective) {
                log.debug("Previous {} next for {} removed", TERMINATION, key);
                if (future != null) {
                    future.complete(null);
                }
            }

            @Override
            public void onError(Objective objective, ObjectiveError error) {
                log.warn("Failed to remove previous {} next for {}: {}", TERMINATION, key, error);
                if (future != null) {
                    future.complete(error);
                }
            }
        };
        srManager.flowObjectiveService.next(egress.deviceId(), (NextObjective) nextObjective.copy().remove(context));
        */

        // delete the extra filtering objective for terminating
        // spine-spine pws
        if (!l2Tunnel.transportVlan().equals(UNTAGGED_TRANSPORT_VLAN)) {

            // determine the input port at the
            PortNumber inPort;

            if (egress.deviceId().
                    equals(l2Tunnel.pathUsed().get(0).dst().deviceId())) {
                inPort = l2Tunnel.pathUsed().get(0).dst().port();
            } else {
                inPort = l2Tunnel.pathUsed().get(0).src().port();
            }

            MacAddress dstMac;
            try {
                dstMac = srManager.deviceConfiguration().getDeviceMac(egress.deviceId());
            } catch (Exception e) {
                log.info("Device not found in configuration, no programming of MAC address");
                dstMac = null;
            }

            log.info("Removing filtering objective for pseudowire transport" +
                             " with vlan = {}, port = {}, mac = {}",
                     l2Tunnel.transportVlan(),
                     inPort,
                     dstMac);
            FilteringObjective.Builder filteringObjectiveBuilder =
                    createNormalPipelineFiltObjective(inPort, l2Tunnel.transportVlan(), dstMac);
            context = new DefaultObjectiveContext(( objective ) ->
                                                          log.debug("Special filtObj for  " + "for {} removed",
                                                                    l2Tunnel.tunnelId()), ( objective, error ) ->
                    log.warn("Failed to populate " + "special filtObj " +
                                     "rule for {}: {}", l2Tunnel.tunnelId(), error));
            TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
            filteringObjectiveBuilder.withMeta(treatment.build());
            srManager.flowObjectiveService.filter(egress.deviceId(), filteringObjectiveBuilder.remove(context));
            log.debug("Removing special FiltObj for termination point with tunnel {} for port {}",
                      l2Tunnel.tunnelId(),
                      inPort);
        }

        l2TerminationNextObjStore.remove(key);
        future.complete(null);
    }

    /**
     * Utilities to generate pw key.
     *
     * @param tunnelId  the tunnel id
     * @param direction the direction of the pw
     * @return the key of the store
     */
    private String generateKey(long tunnelId, Direction direction) {
        return String.format("%s-%s", tunnelId, direction);
    }

}
