/*
 * 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.config.NetworkConfigEvent;
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.segmentrouting.SegmentRoutingManager;
import org.onosproject.segmentrouting.SegmentRoutingService;
import org.onosproject.segmentrouting.config.DeviceConfigNotFoundException;
import org.onosproject.segmentrouting.config.PwaasConfig;
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.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

import static com.google.common.base.Preconditions.checkArgument;
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;

/**
 * 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;

    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();

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

    /**
     * Deploys any pre-existing pseudowires in the configuration.
     * Used by manager only in initialization.
     */
    @Override
    public void init() {

        PwaasConfig config = srManager.cfgService.getConfig(srManager.appId(), PwaasConfig.class);
        if (config == null) {
            return;
        }

        log.info("Deploying existing pseudowires");

        // gather pseudowires
        Set<L2TunnelDescription> pwToAdd = config
                .getPwIds()
                .stream()
                .map(config::getPwDescription)
                .collect(Collectors.toSet());

        // deploy pseudowires
        deploy(pwToAdd);
    }

    /**
     * Returns all L2 Policies.
     *
     * @return List of policies
     */
    @Override
    public List<L2TunnelPolicy> getL2Policies() {

        return new ArrayList<>(l2PolicyStore
                .values()
                .stream()
                .map(Versioned::value)
                .collect(Collectors.toList()));

    }

    /**
     * Returns all L2 Tunnels.
     *
     * @return List of tunnels.
     */
    @Override
    public List<L2Tunnel> getL2Tunnels() {

        return new ArrayList<>(l2TunnelStore
                .values()
                .stream()
                .map(Versioned::value)
                .collect(Collectors.toList()));

    }

    @Override
    public void processLinkDown(Link link) {

        List<L2Tunnel> tunnels = getL2Tunnels();
        List<L2TunnelPolicy> policies = getL2Policies();

        // determine affected pseudowires and update them at once
        Set<L2TunnelDescription> pwToUpdate = tunnels
                .stream()
                .filter(tun -> tun.pathUsed().contains(link))
                .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());


        log.info("Pseudowires affected by link failure : {}, rerouting them...", pwToUpdate);

        // update all pseudowires
        pwToUpdate.forEach(tun -> updatePw(tun, tun));
    }

    @Override
    public void processPwaasConfigAdded(NetworkConfigEvent event) {
        checkArgument(event.config().isPresent(),
                "Config is not presented in PwaasConfigAdded event {}", event);

        log.info("Network event : Pseudowire configuration added!");
        PwaasConfig config = (PwaasConfig) event.config().get();

        // gather pseudowires
        Set<L2TunnelDescription> pwToAdd = config
                .getPwIds()
                .stream()
                .map(config::getPwDescription)
                .collect(Collectors.toSet());

        // deploy pseudowires
        deploy(pwToAdd);
    }

    /**
     * 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((short) 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;
        }
    }

    /**
     * Adds a single pseudowire from leaf to a leaf.
     * This method can be called from cli commands
     * without configuration updates, thus it does not check for mastership
     * of the ingress pseudowire device.
     *
     * @param pw The pseudowire
     * @param spinePw True if pseudowire is from leaf to spine
     * @return result of pseudowire deployment
     */
    private Result deployPseudowire(L2TunnelDescription pw, boolean spinePw) {

        Result result;
        long l2TunnelId;

        l2TunnelId = pw.l2Tunnel().tunnelId();

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

        // 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.info("Deploying process : No path between the connection points for pseudowire {}", l2TunnelId);
            return WRONG_PARAMETERS;
        }

        Link fwdNextHop;
        Link revNextHop;
        if (!spinePw) {
            if (path.size() != 2) {
                log.info("Deploying process : Path between two leafs should have size of 2, for pseudowire {}",
                         l2TunnelId);
                return INTERNAL_ERROR;
            }

            fwdNextHop = path.get(0);
            revNextHop = reverseLink(path.get(1));
        } else {
            if (path.size() != 1) {
                log.info("Deploying process : Path between leaf spine should equal to 1, for pseudowire {}",
                         l2TunnelId);
                return INTERNAL_ERROR;
            }

            fwdNextHop = path.get(0);
            revNextHop = reverseLink(path.get(0));
        }

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

        // 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,
                                      spinePw,
                                      egressVlan);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
            return Result.ADDITION_ERROR;
        }

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

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

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

        }

        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,
                                       spinePw,
                                       egressVlan);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire initiation for CP2");
            return Result.ADDITION_ERROR;
        }


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

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

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

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

        // Populate stores
        l2TunnelStore.put(Long.toString(l2TunnelId), pw.l2Tunnel());
        l2PolicyStore.put(Long.toString(l2TunnelId), pw.l2TunnelPolicy());

        return Result.SUCCESS;
    }

    /**
     * To deploy a number of pseudo wires.
     * <p>
     * Called ONLY when configuration changes, thus the check
     * for the mastership of the device.
     * <p>
     * Only the master of CP1 will deploy this pseudowire.
     *
     * @param pwToAdd the set of pseudo wires to add
     */
    private void deploy(Set<L2TunnelDescription> pwToAdd) {

        Result result;

        for (L2TunnelDescription currentL2Tunnel : pwToAdd) {
            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();

            // only the master of CP1 will program this pseudowire
            if (!srManager.isMasterOf(cp1)) {
                log.debug("Not the master of {}. Ignore pseudo wire deployment id={}", cp1, tunnelId);
                continue;
            }

            try {
                // differentiate between leaf-leaf pseudowires and leaf-spine
                // and pass the appropriate flag in them.
                if (!srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
                    !srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
                    log.warn("Can not deploy pseudowire from spine to spine!");
                    result = Result.INTERNAL_ERROR;
                } else if (srManager.deviceConfiguration().isEdgeDevice(cp1.deviceId()) &&
                     srManager.deviceConfiguration().isEdgeDevice(cp2.deviceId())) {
                    log.info("Deploying a leaf-leaf pseudowire {}", tunnelId);
                    result = deployPseudowire(currentL2Tunnel, false);
                } else {
                    log.info("Deploying a leaf-spine pseudowire {}", tunnelId);
                    result = deployPseudowire(currentL2Tunnel, true);
                }
            } catch (DeviceConfigNotFoundException e) {
                log.error("Exception caught when deploying pseudowire", e.toString());
                result = Result.INTERNAL_ERROR;
            }

            switch (result) {
                case INTERNAL_ERROR:
                    log.warn("Could not deploy pseudowire {}, internal error!", tunnelId);
                    break;
                case WRONG_PARAMETERS:
                    log.warn("Could not deploy pseudowire {}, wrong parameters!", tunnelId);
                    break;
                case ADDITION_ERROR:
                    log.warn("Could not deploy pseudowire {}, error in populating rules!", tunnelId);
                    break;
                default:
                    log.info("Pseudowire with {} succesfully deployed!", tunnelId);
                    break;
            }
        }
    }


    @Override
    public void processPwaasConfigUpdated(NetworkConfigEvent event) {
        checkArgument(event.config().isPresent(),
                "Config is not presented in PwaasConfigUpdated event {}", event);
        checkArgument(event.prevConfig().isPresent(),
                "PrevConfig is not presented in PwaasConfigUpdated event {}", event);

        log.info("Pseudowire configuration updated.");

        // We retrieve the old pseudo wires.
        PwaasConfig prevConfig = (PwaasConfig) event.prevConfig().get();
        Set<Long> prevPws = prevConfig.getPwIds();

        // We retrieve the new pseudo wires.
        PwaasConfig config = (PwaasConfig) event.config().get();
        Set<Long> newPws = config.getPwIds();

        // We compute the pseudo wires to update.
        Set<Long> updPws = newPws.stream()
                .filter(tunnelId -> prevPws.contains(tunnelId)
                        && !config.getPwDescription(tunnelId).equals(prevConfig.getPwDescription(tunnelId)))
                .collect(Collectors.toSet());

        // The pseudo wires to remove.
        Set<Long> rmvPWs = prevPws.stream()
                .filter(tunnelId -> !newPws.contains(tunnelId)).collect(Collectors.toSet());

        Set<L2TunnelDescription> pwToRemove = rmvPWs.stream()
                .map(prevConfig::getPwDescription)
                .collect(Collectors.toSet());
        tearDown(pwToRemove);

        // The pseudo wires to add.
        Set<Long> addedPWs = newPws.stream()
                .filter(tunnelId -> !prevPws.contains(tunnelId))
                .collect(Collectors.toSet());
        Set<L2TunnelDescription> pwToAdd = addedPWs.stream()
                .map(config::getPwDescription)
                .collect(Collectors.toSet());
        deploy(pwToAdd);


        // The pseudo wires to update.
        updPws.forEach(tunnelId -> updatePw(prevConfig.getPwDescription(tunnelId),
                                            config.getPwDescription(tunnelId)));

        log.info("Pseudowires removed : {}, Pseudowires updated : {}, Pseudowires added : {}", rmvPWs,
                 updPws, addedPWs);
    }

    /**
     * Helper function to update a pw.
     * <p>
     * Called upon configuration changes that update existing pseudowires and
     * when links fail. Checking of mastership for CP1 is mandatory because it is
     * called in multiple instances for both cases.
     * <p>
     * Meant to call asynchronously for various events, thus this call can not block and need
     * to perform asynchronous operations.
     * <p>
     * For this reason error checking is omitted.
     *
     * @param oldPw the pseudo wire to remove
     * @param newPw the pseudo wire to add
     */
    private void updatePw(L2TunnelDescription oldPw,
                         L2TunnelDescription newPw) {
        ConnectPoint oldCp1 = oldPw.l2TunnelPolicy().cP1();
        long tunnelId = oldPw.l2Tunnel().tunnelId();

        // only the master of CP1 will update this pseudowire
        if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) {
            log.debug("Not the master of {}. Ignore pseudo wire update id={}", oldCp1, tunnelId);
            return;
        }
        // only determine if the new pseudowire is leaf-spine, because
        // removal process is the same for both leaf-leaf and leaf-spine pws
        boolean newPwSpine;
        try {
            newPwSpine = !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP1().deviceId()) ||
                    !srManager.deviceConfiguration().isEdgeDevice(newPw.l2TunnelPolicy().cP2().deviceId());
        } catch (DeviceConfigNotFoundException e) {
            // if exception is caught treat the new pw as leaf-leaf
            newPwSpine = false;
        }

        // copy the variable here because we need to use it in lambda thus it needs to be final
        boolean finalNewPwSpine = newPwSpine;

        log.info("Updating pseudowire {}", oldPw.l2Tunnel().tunnelId());

        // The async tasks to orchestrate the next and forwarding update
        CompletableFuture<ObjectiveError> fwdInitNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> revInitNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> fwdTermNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> revTermNextFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> fwdPwFuture = new CompletableFuture<>();
        CompletableFuture<ObjectiveError> revPwFuture = new CompletableFuture<>();

        // first delete all information from our stores, we can not do it asynchronously
        l2PolicyStore.remove(Long.toString(tunnelId));

        // grab the old l2 tunnel from the store, since it carries information which is not exposed
        // to the user configuration and set it to oldPw.
        oldPw.setL2Tunnel(l2TunnelStore.get(Long.toString(tunnelId)).value());
        VlanId transportVlan = l2TunnelStore.get(Long.toString(tunnelId)).value().transportVlan();
        l2TunnelStore.remove(Long.toString(tunnelId));

        // remove the reserved transport vlan, if one is used
        if (!transportVlan.equals(UNTAGGED_TRANSPORT_VLAN)) {
            vlanStore.remove(transportVlan);
        }

        // First we remove both policy.
        log.debug("Start deleting fwd policy for {}", tunnelId);
        VlanId egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP1OuterTag(),
                                                 oldPw.l2TunnelPolicy().cP1InnerTag(),
                                                 oldPw.l2TunnelPolicy().cP2OuterTag(),
                                                 oldPw.l2TunnelPolicy().cP2InnerTag());
        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP1(),
                      oldPw.l2TunnelPolicy().cP1InnerTag(),
                      oldPw.l2TunnelPolicy().cP1OuterTag(),
                      egressVlan,
                      fwdInitNextFuture,
                      FWD);

        deletePolicy(tunnelId, oldPw.l2TunnelPolicy().cP2(),
                      oldPw.l2TunnelPolicy().cP2InnerTag(),
                      oldPw.l2TunnelPolicy().cP2OuterTag(),
                      egressVlan, revInitNextFuture,
                      REV);

        // Finally we remove both the tunnels.
        fwdInitNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Update process : Fwd policy removed. " +
                                  "Now remove fwd {} for {}", INITIATION, tunnelId);
                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP1(), fwdTermNextFuture, FWD);
            }
        });
        revInitNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Update process : Rev policy removed. " +
                                  "Now remove rev {} for {}", INITIATION, tunnelId);
                tearDownPseudoWireInit(tunnelId, oldPw.l2TunnelPolicy().cP2(), revTermNextFuture, REV);
            }
        });
        fwdTermNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Update process : Fwd {} removed. " +
                                  "Now remove fwd {} for {}", INITIATION, TERMINATION, tunnelId);
                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP2(),  fwdPwFuture, FWD);
            }
        });
        revTermNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Update process : Rev {} removed. " +
                                  "Now remove rev {} for {}", INITIATION, TERMINATION, tunnelId);
                tearDownPseudoWireTerm(oldPw.l2Tunnel(), oldPw.l2TunnelPolicy().cP1(), revPwFuture, REV);
            }
        });

        // get path here, need to use the same for fwd and rev direction
        List<Link> path = getPath(newPw.l2TunnelPolicy().cP1(),
                                   newPw.l2TunnelPolicy().cP2());
        if (path == null) {
            log.error("Update process : " +
                             "No path between the connection points for pseudowire {}", newPw.l2Tunnel().tunnelId());
            return;
        }

        Link fwdNextHop, revNextHop;
        if (!finalNewPwSpine) {
            if (path.size() != 2) {
                log.error("Update process : Error, path between two leafs should have size of 2, for pseudowire {}",
                         newPw.l2Tunnel().tunnelId());
                return;
            }
            fwdNextHop = path.get(0);
            revNextHop = reverseLink(path.get(1));
        } else {
            if (path.size() != 1) {
                log.error("Update process : Error, path between leaf spine should equal to 1, for pseudowire {}",
                         newPw.l2Tunnel().tunnelId());
                return;
            }
            fwdNextHop = path.get(0);
            revNextHop = reverseLink(path.get(0));
        }

        // set new path and transport vlan.
        newPw.l2Tunnel().setPath(path);
        newPw.l2Tunnel().setTransportVlan(determineTransportVlan(newPwSpine));

        // At the end we install the updated PW.
        fwdPwFuture.thenAcceptAsync(status -> {
            if (status == null) {

                // Upgrade stores and book keeping information, need to move this here
                // cause this call is asynchronous.
                l2PolicyStore.put(Long.toString(tunnelId), newPw.l2TunnelPolicy());
                l2TunnelStore.put(Long.toString(tunnelId), newPw.l2Tunnel());

                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP1OuterTag(),
                                                          newPw.l2TunnelPolicy().cP1InnerTag(),
                                                          newPw.l2TunnelPolicy().cP2OuterTag(),
                                                          newPw.l2TunnelPolicy().cP2InnerTag());

                log.debug("Update process : Deploying new fwd pw for {}", tunnelId);
                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP1(),
                                                           newPw.l2TunnelPolicy().cP2(), FWD,
                                                           fwdNextHop, finalNewPwSpine, egressVlanId);
                if (lamdaResult != SUCCESS) {
                    return;
                }

                lamdaResult = deployPolicy(tunnelId, newPw.l2TunnelPolicy().cP1(),
                                            newPw.l2TunnelPolicy().cP1InnerTag(),
                                           newPw.l2TunnelPolicy().cP1OuterTag(),
                                            egressVlanId, lamdaResult.nextId);
                if (lamdaResult != SUCCESS) {
                    return;
                }
                deployPseudoWireTerm(newPw.l2Tunnel(), newPw.l2TunnelPolicy().cP2(),
                                      egressVlanId, FWD, finalNewPwSpine);

            }
        });
        revPwFuture.thenAcceptAsync(status -> {
            if (status == null) {

                log.debug("Update process : Deploying new rev pw for {}", tunnelId);

                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP2OuterTag(),
                                                          newPw.l2TunnelPolicy().cP2InnerTag(),
                                                          newPw.l2TunnelPolicy().cP1OuterTag(),
                                                          newPw.l2TunnelPolicy().cP1InnerTag());

                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(),
                                                           newPw.l2TunnelPolicy().cP2(),
                                                           newPw.l2TunnelPolicy().cP1(),
                                                           REV,
                                                           revNextHop, finalNewPwSpine, egressVlanId);
                if (lamdaResult != SUCCESS) {
                    return;
                }

                lamdaResult = deployPolicy(tunnelId,
                                            newPw.l2TunnelPolicy().cP2(),
                                            newPw.l2TunnelPolicy().cP2InnerTag(),
                                            newPw.l2TunnelPolicy().cP2OuterTag(),
                                            egressVlanId,
                                            lamdaResult.nextId);
                if (lamdaResult != SUCCESS) {
                    return;
                }
                deployPseudoWireTerm(newPw.l2Tunnel(),
                                      newPw.l2TunnelPolicy().cP1(),
                                      egressVlanId,
                                      REV, finalNewPwSpine);
            }
        });
    }

    @Override
    public void processPwaasConfigRemoved(NetworkConfigEvent event) {
        checkArgument(event.prevConfig().isPresent(),
                "PrevConfig is not presented in PwaasConfigRemoved event {}", event);

        log.info("Network event : Pseudowire configuration removed!");
        PwaasConfig config = (PwaasConfig) event.prevConfig().get();

        Set<L2TunnelDescription> pwToRemove = config
                .getPwIds()
                .stream()
                .map(config::getPwDescription)
                .collect(Collectors.toSet());

        // We teardown all the pseudo wire deployed
        tearDown(pwToRemove);
    }

    /**
     * Helper function for removing a single pseudowire.
     * <p>
     * No mastership of CP1 is checked, because it can be called from
     * the CLI for removal of pseudowires.
     *
     * @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
     */
    private Result tearDownPseudowire(long l2TunnelId) {

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

        // check existence of tunnels/policy in the store, if one is missing abort!
        Versioned<L2Tunnel> l2TunnelVersioned = l2TunnelStore.get(Long.toString(l2TunnelId));
        Versioned<L2TunnelPolicy> l2TunnelPolicyVersioned = l2PolicyStore.get(Long.toString(l2TunnelId));
        if ((l2TunnelVersioned == null) || (l2TunnelPolicyVersioned == null)) {
            log.warn("Removal process : Policy and/or tunnel missing for tunnel id {}", l2TunnelId);
            return Result.REMOVAL_ERROR;
        }

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

        // remove the tunnels and the policies from the store
        l2PolicyStore.remove(Long.toString(l2TunnelId));
        l2TunnelStore.remove(Long.toString(l2TunnelId));

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

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

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

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

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

        Result result;

        // We remove all the pw in the configuration file.
        for (L2TunnelDescription currentL2Tunnel : pwToRemove) {
            ConnectPoint cp1 = currentL2Tunnel.l2TunnelPolicy().cP1();
            ConnectPoint cp2 = currentL2Tunnel.l2TunnelPolicy().cP2();
            long tunnelId = currentL2Tunnel.l2TunnelPolicy().tunnelId();

            // only the master of CP1 will program this pseudowire
            if (!srManager.isMasterOf(cp1)) {
                log.debug("Not the master of {}. Ignore pseudo wire removal id={}", cp1, tunnelId);
                continue;
            }

            // no need to differentiate here between leaf-leaf and leaf-spine, because
            // the only change is in the groups, which we do not remove either way
            log.info("Removing pseudowire {}", tunnelId);

            result = tearDownPseudowire(tunnelId);
            switch (result) {
                case WRONG_PARAMETERS:
                    log.warn("Error in supplied parameters for the pseudowire removal with tunnel id {}!",
                            tunnelId);
                    break;
                case REMOVAL_ERROR:
                    log.warn("Error in pseudowire removal with tunnel id {}!", tunnelId);
                    break;
                default:
                    log.warn("Pseudowire with tunnel id {} was removed successfully", 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, 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,
                                                                         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.nextId = 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) {

        // We create the group relative to the termination.
        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
                                                                         l2Tunnel, egress.deviceId(),
                                                                         spinePw,
                                                                         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 spinePw if the pw involves a spine switch
     * @return the next objective to support the pipeline
     */
    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
                                                      ConnectPoint dstCp,  L2Tunnel l2Tunnel,
                                                      DeviceId egressId, boolean spinePw, 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 pw is leaf-to-leaf we need to
            // add the routing label also
            if (!spinePw) {
                // 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 not a leaf-spine pw we need to POP the vlan at the output
            // since we carry this traffic untagged.
            if (!spinePw) {
                treatmentBuilder.popVlan();
            }

            // set the appropriate transport vlan
            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;
    }

    /**
     * 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) {
        /* TODO We retrieve a set of paths in case of a link failure, what happens
         * if the TopologyService gets the link notification AFTER us and has not updated the paths?
         *
         * TODO This has the potential to act on old topology.
         * Maybe we should make SRManager be a listener on topology events instead raw link events.
         */
        Set<Path> paths = srManager.topologyService.getPaths(
                srManager.topologyService.currentTopology(),
                srcCp.deviceId(), dstCp.deviceId());

        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;
        }
        NextObjective nextObjective = l2InitiationNextObjStore.get(key).value();

        // 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)
        /*
        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);
    }

}
