/*
 * 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.DisjointPath;
import org.onosproject.net.Link;
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.Serializer;
import org.onosproject.store.service.Versioned;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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;

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

    private static final Logger log = LoggerFactory.getLogger(L2TunnelHandler.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, DefaultL2TunnelPolicy> l2PolicyStore;

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

    private final KryoNamespace.Builder l2TunnelKryo;

    /**
     * Create a l2 tunnel handler for the deploy and
     * for the tear down of pseudo wires.
     *
     * @param segmentRoutingManager the segment routing manager
     */
    public L2TunnelHandler(SegmentRoutingManager segmentRoutingManager) {
        srManager = segmentRoutingManager;
        l2TunnelKryo = new KryoNamespace.Builder()
                .register(KryoNamespaces.API)
                .register(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, DefaultL2TunnelPolicy>consistentMapBuilder()
                .withName("onos-l2-policy-store")
                .withSerializer(Serializer.using(l2TunnelKryo.build()))
                .build();

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

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

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

    }

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

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

    }

    /**
     * Processes a link removal. Finds affected pseudowires and rewires them.
     * TODO: Make it also take into account failures of links that are used for pw
     * traffic in the spine.
     * @param link The link that failed
     */
    public void processLinkDown(Link link) {

        List<DefaultL2Tunnel> tunnels = getL2Tunnels();
        List<DefaultL2TunnelPolicy> policies = getL2Policies();

        // determine affected pseudowires and update them at once
        Set<DefaultL2TunnelDescription> pwToUpdate = tunnels
                .stream()
                .filter(tun -> tun.pathUsed().contains(link))
                .map(l2Tunnel -> {
                        DefaultL2TunnelPolicy policy = null;
                        for (DefaultL2TunnelPolicy 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));
    }

    /**
     * Processes Pwaas Config added event.
     *
     * @param event network config add event
     */
    public void processPwaasConfigAdded(NetworkConfigEvent event) {

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

        // gather pseudowires
        Set<DefaultL2TunnelDescription> 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.
     */
    public 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");
        }
    }

    /**
     * Adds a single pseudowire. This method can be called from cli commands
     * without configration updates, thus it does not check for mastership
     * of the ingress pseudowire device.
     *
     * @param pw The pseudowire
     * @return
     */
    private Result deployPseudowire(DefaultL2TunnelDescription pw) {

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

        pw.l2Tunnel().setPath(path);

        // next hops for next objectives
        Link fwdNextHop = path.get(0);
        Link revNextHop = reverseLink(path.get(1));

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

        // We establish the tunnel.
        // result.nextId will be used in fwd
        result = deployPseudoWireInit(pw.l2Tunnel(),
                                      pw.l2TunnelPolicy().cP1(),
                                      pw.l2TunnelPolicy().cP2(),
                                      FWD,
                                      fwdNextHop);
        if (result != SUCCESS) {
            log.info("Deploying process : Error in deploying pseudowire initiation for CP1");
            return Result.ADDITION_ERROR;
        }

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

        // 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(),
                                       pw.l2TunnelPolicy().cP2OuterTag(),
                                       FWD);

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

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

        egressVlan = determineEgressVlan(pw.l2TunnelPolicy().cP2OuterTag(),
                                          pw.l2TunnelPolicy().cP2InnerTag(),
                                          pw.l2TunnelPolicy().cP1OuterTag(),
                                          pw.l2TunnelPolicy().cP1InnerTag());
        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(),
                                       pw.l2TunnelPolicy().cP1OuterTag(),
                                       REV);

        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<DefaultL2TunnelDescription> pwToAdd) {

        Result result;

        for (DefaultL2TunnelDescription currentL2Tunnel : pwToAdd) {

            // only the master of CP1 will program this pseudowire
            if (!srManager.isMasterOf(currentL2Tunnel.l2TunnelPolicy().cP1())) {
                continue;
            }

            log.info("Deploying pseudowire {}", currentL2Tunnel.l2Tunnel().tunnelId());

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

    /**
     * Processes PWaaS Config updated event.
     *
     * @param event network config updated event
     */
    public void processPwaasConfigUpdated(NetworkConfigEvent 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<DefaultL2TunnelDescription> 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<DefaultL2TunnelDescription> 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
     */
    public void updatePw(DefaultL2TunnelDescription oldPw, DefaultL2TunnelDescription newPw) {
        long tunnelId = oldPw.l2Tunnel().tunnelId();

        // only the master of CP1 will update this pseudowire
        if (!srManager.isMasterOf(oldPw.l2TunnelPolicy().cP1())) {
            return;
        }

        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 we remove both policy.
        log.debug("Start deleting fwd policy for {}", tunnelId);

        // first delete all information from our stores
        // we can not do it asynchronously
        l2PolicyStore.remove(Long.toString(tunnelId));
        l2TunnelStore.remove(Long.toString(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);

        log.debug("Update process : Start deleting rev policy for {}", tunnelId);

        egressVlan = determineEgressVlan(oldPw.l2TunnelPolicy().cP2OuterTag(),
                                          oldPw.l2TunnelPolicy().cP2InnerTag(),
                                          oldPw.l2TunnelPolicy().cP1OuterTag(),
                                          oldPw.l2TunnelPolicy().cP1InnerTag());
        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.info("Deploying process : " +
                             "No path between the connection points for pseudowire {}", newPw.l2Tunnel().tunnelId());
            return;
        }

        newPw.l2Tunnel().setPath(path);
        // next hops for next objectives
        Link fwdNextHop = path.get(0);
        Link revNextHop = reverseLink(path.get(1));

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

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

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

                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(),
                                      newPw.l2TunnelPolicy().cP2OuterTag(),
                                      FWD);

            }
        });

        revPwFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Update process : Deploying new rev pw for {}", tunnelId);
                Result lamdaResult = deployPseudoWireInit(newPw.l2Tunnel(),
                                                           newPw.l2TunnelPolicy().cP2(),
                                                           newPw.l2TunnelPolicy().cP1(),
                                                           REV,
                                                           revNextHop);
                if (lamdaResult != SUCCESS) {
                    return;
                }

                VlanId egressVlanId = determineEgressVlan(newPw.l2TunnelPolicy().cP2OuterTag(),
                                                           newPw.l2TunnelPolicy().cP2InnerTag(),
                                                           newPw.l2TunnelPolicy().cP1OuterTag(),
                                                           newPw.l2TunnelPolicy().cP1InnerTag());
                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(),
                                      newPw.l2TunnelPolicy().cP1OuterTag(),
                                      REV);
            }
        });
    }

    /**
     * Processes Pwaas Config removed event.
     *
     * @param event network config removed event
     */
    public void processPwaasConfigRemoved(NetworkConfigEvent event) {

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

        Set<DefaultL2TunnelDescription> 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
     */
    public 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<DefaultL2Tunnel> l2TunnelVersioned = l2TunnelStore.get(Long.toString(l2TunnelId));
        Versioned<DefaultL2TunnelPolicy> 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;
        }

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

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

    /**
     * Helper function to handle the pw removal.
     * <p>
     * This method checks for the mastership of the device because it is
     * used only from network configuration updates, thus we only want
     * one instance only to program each pseudowire.
     *
     * @param pwToRemove the pseudo wires to remove
     */
    public void tearDown(Set<DefaultL2TunnelDescription> pwToRemove) {

        Result result;

        // We remove all the pw in the configuration file.
        for (DefaultL2TunnelDescription currentL2Tunnel : pwToRemove) {

            // only the master of CP1 will program this pseudowire
            if (!srManager.isMasterOf(currentL2Tunnel.l2TunnelPolicy().cP1())) {
                continue;
            }

            log.info("Removing pseudowire {}", currentL2Tunnel.l2Tunnel().tunnelId());

            result = tearDownPseudowire(currentL2Tunnel.l2Tunnel().tunnelId());
            switch (result) {
                case WRONG_PARAMETERS:
                    log.warn("Error in supplied parameters for the pseudowire removal with tunnel id {}!",
                             currentL2Tunnel.l2Tunnel().tunnelId());
                    break;
                case REMOVAL_ERROR:
                    log.warn("Error in pseudowire removal with tunnel id {}!", currentL2Tunnel.l2Tunnel().tunnelId());
                    break;
                default:
                    log.warn("Pseudowire with tunnel id {} was removed successfully",
                             currentL2Tunnel.l2Tunnel().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
     * @return the result of the operation
     */
    private Result deployPseudoWireInit(DefaultL2Tunnel l2Tunnel, ConnectPoint ingress,
                                        ConnectPoint egress, Direction direction, Link nextHop) {

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

        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
     * @return the result of the operation
     */
    private Result deployPseudoWireTerm(DefaultL2Tunnel l2Tunnel, ConnectPoint egress,
                                        VlanId egressVlan, Direction direction) {

        // We create the group relative to the termination.
        NextObjective.Builder nextObjectiveBuilder = createNextObjective(TERMINATION, egress, null,
                                                                         null, egress.deviceId());
        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());
        return SUCCESS;

    }

    /**
     * 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
     * @return the next objective to support the pipeline
     */
    private NextObjective.Builder createNextObjective(Pipeline pipeline, ConnectPoint srcCp,
                                                      ConnectPoint dstCp,  DefaultL2Tunnel l2Tunnel,
                                                      DeviceId egressId) {
        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();
            }
            // 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);
        } else {
            // We create the next objective which
            // will be a simple l2 group.
            nextObjBuilder = DefaultNextObjective
                    .builder()
                    .withType(NextObjective.Type.SIMPLE)
                    .fromApp(srManager.appId());
        }
        treatmentBuilder.setOutput(srcCp.port());
        nextObjBuilder.addTreatment(treatmentBuilder.build());
        return nextObjBuilder;
    }

    /**
     * Reverses a link.
     *
     * @param link
     * @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
     * @param dstCp
     * @return The path
     */
    private List<Link> getPath(ConnectPoint srcCp, ConnectPoint dstCp) {

        /* We retrieve a set of disjoint paths.
        * We perform that in case of a link failure, what happens
        * if the PathService gets the link notification AFTER us and
        * has not updated the paths?
        */
        Set<DisjointPath> paths = srManager
                .pathService
                .getDisjointPaths(srcCp.elementId(), dstCp.elementId());

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

        return Iterables.get(paths, index).links();
    }

    /**
     * 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(DefaultL2Tunnel 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 {} {} removed",
                                                                                        TERMINATION,
                                                                                        l2Tunnel.tunnelId()),
                                                               (objective, error) ->
                                                                       log.warn("Failed to remove fwdObj for {} {}",
                                                                                TERMINATION,
                                                                                l2Tunnel.tunnelId(),
                                                                                error));
        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));
        */

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

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

    /**
     * Pwaas pipelines.
     */
    protected enum Pipeline {
        /**
         * The initiation pipeline.
         */
        INITIATION, /**
         * The termination pipeline.
         */
        TERMINATION
    }

    /**
     * Enum helper to carry results of various operations.
     */
    public enum Result {
        /**
         * Happy ending scenario.
         */
        SUCCESS(0, "No error occurred"),

        /**
         * We have problems with the supplied parameters.
         */
        WRONG_PARAMETERS(1, "Wrong parameters"),

        /**
         * We have an internal error during the deployment
         * or removal phase.
         */
        INTERNAL_ERROR(3, "Internal error"),

        /**
         *
         */
        REMOVAL_ERROR(5, "Can not remove pseudowire from network configuration"),

        /**
         *
         */
        ADDITION_ERROR(6, "Can not add pseudowire in network configuration"),

        /**
         *
         */
        CONFIG_NOT_FOUND(7, "Can not find configuration class for pseudowires");

        private final int code;
        private final String description;
        private int nextId;

        Result(int code, String description) {
            this.code = code;
            this.description = description;
        }

        public String getDescription() {
            return description;
        }

        @Override
        public String toString() {
            return code + ": " + description;
        }
    }

    /**
     * Enum helper for handling the direction of the pw.
     */
    public enum Direction {
        /**
         * The forward direction of the pseudo wire.
         */
        FWD, /**
         * The reverse direction of the pseudo wire.
         */
        REV
    }

}
