/*
 * 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.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.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 com.google.common.base.Preconditions.checkState;
import static org.onosproject.net.flowobjective.ForwardingObjective.Flag.VERSATILE;
import static org.onosproject.segmentrouting.pwaas.L2Mode.TAGGED;
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);
    /**
     * Error message for invalid paths.
     */
    private static final String WRONG_TOPOLOGY = "Path in leaf-spine topology" +
            " should always be two hops: ";

    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;
    /**
     * TODO a proper store is necessary to handle the policies, collisions and recovery.
     * We should have a proper store for the policies and the tunnels. For several reasons:
     * 1) We should avoid the overlapping of different policies;
     * 2) We should avoid the overlapping of different tunnels;
     * 3) We should have a proper mechanism for the protection;
     * The most important one is 3). At least for 3.0 EA0 was not possible
     * to remove the bucket, so we need a mapping between policies and tunnel
     * in order to proper update the fwd objective for the recovery of a fault.
     */
    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);

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

    /**
     * Processes Pwaas Config added event.
     *
     * @param event network config add event
     */
    public void processPwaasConfigAdded(NetworkConfigEvent event) {
        log.info("Processing Pwaas CONFIG_ADDED");
        PwaasConfig config = (PwaasConfig) event.config().get();
        Set<DefaultL2TunnelDescription> pwToAdd = config.getPwIds()
                .stream()
                .map(config::getPwDescription)
                .collect(Collectors.toSet());
        // We deploy all the pseudo wire deployed
        deploy(pwToAdd);
    }

    /**
     * To deploy a number of pseudo wires.
     *
     * @param pwToAdd the set of pseudo wires to add
     */
    private void deploy(Set<DefaultL2TunnelDescription> pwToAdd) {
        Result result;
        long l2TunnelId;
        for (DefaultL2TunnelDescription currentL2Tunnel : pwToAdd) {
            l2TunnelId = currentL2Tunnel.l2Tunnel().tunnelId();
            // The tunnel id cannot be 0.
            if (l2TunnelId == 0) {
                log.warn("Tunnel id id must be > 0");
                continue;
            }
            // We do a sanity check of the pseudo wire.
            result = verifyPseudoWire(currentL2Tunnel);
            if (result != SUCCESS) {
                continue;
            }
            // We establish the tunnel.
            result = deployPseudoWireInit(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    FWD
            );
            if (result != SUCCESS) {
                continue;
            }
            // We create the policy.
            result = deployPolicy(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    currentL2Tunnel.l2TunnelPolicy().cP1InnerTag(),
                    currentL2Tunnel.l2TunnelPolicy().cP1OuterTag(),
                    result.nextId
            );
            if (result != SUCCESS) {
                continue;
            }
            // We terminate the tunnel
            result = deployPseudoWireTerm(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    currentL2Tunnel.l2TunnelPolicy().cP2OuterTag(),
                    FWD
            );
            if (result != SUCCESS) {
                continue;
            }
            // We establish the reverse tunnel.
            result = deployPseudoWireInit(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    REV
            );
            if (result != SUCCESS) {
                continue;
            }
            result = deployPolicy(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    currentL2Tunnel.l2TunnelPolicy().cP2InnerTag(),
                    currentL2Tunnel.l2TunnelPolicy().cP2OuterTag(),
                    result.nextId
            );
            if (result != SUCCESS) {
                continue;
            }
            deployPseudoWireTerm(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    currentL2Tunnel.l2TunnelPolicy().cP1OuterTag(),
                    REV
            );
        }
    }

    /**
     * Processes PWaaS Config updated event.
     *
     * @param event network config updated event
     */
    public void processPwaasConfigUpdated(NetworkConfigEvent event) {
        log.info("Processing Pwaas CONFIG_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<DefaultL2TunnelDescription> pwToRemove = prevPws.stream()
                .filter(tunnelId -> !newPws.contains(tunnelId))
                .map(prevConfig::getPwDescription)
                .collect(Collectors.toSet());
        tearDown(pwToRemove);
        // The pseudo wires to add.
        Set<DefaultL2TunnelDescription> pwToAdd = newPws.stream()
                .filter(tunnelId -> !prevPws.contains(tunnelId))
                .map(config::getPwDescription)
                .collect(Collectors.toSet());
        deploy(pwToAdd);
        // The pseudo wires to update.
        updPws.forEach(tunnelId -> updatePw(
                prevConfig.getPwDescription(tunnelId),
                config.getPwDescription(tunnelId))
        );
    }

    /**
     * Helper function to update a pw.
     *
     * @param oldPw the pseudo wire to remove
     * @param newPw the pseudo wirte to add
     */
    private void updatePw(DefaultL2TunnelDescription oldPw,
                          DefaultL2TunnelDescription newPw) {
        long tunnelId = 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<>();


        Result result = verifyPseudoWire(newPw);
        if (result != SUCCESS) {
            return;
        }
        // First we remove both policy.
        log.debug("Start deleting fwd policy for {}", tunnelId);
        deletePolicy(
                tunnelId,
                oldPw.l2TunnelPolicy().cP1(),
                oldPw.l2TunnelPolicy().cP1InnerTag(),
                oldPw.l2TunnelPolicy().cP1OuterTag(),
                fwdInitNextFuture,
                FWD
        );
        log.debug("Start deleting rev policy for {}", tunnelId);
        deletePolicy(
                tunnelId,
                oldPw.l2TunnelPolicy().cP2(),
                oldPw.l2TunnelPolicy().cP2InnerTag(),
                oldPw.l2TunnelPolicy().cP2OuterTag(),
                revInitNextFuture,
                REV
        );
        // Finally we remove both the tunnels.
        fwdInitNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Fwd policy removed. Now remove fwd {} for {}", INITIATION, tunnelId);
                tearDownPseudoWireInit(
                        tunnelId,
                        oldPw.l2TunnelPolicy().cP1(),
                        fwdTermNextFuture,
                        FWD
                );
            }
        });
        revInitNextFuture.thenAcceptAsync(status -> {
           if (status == null) {
               log.debug("Rev policy removed. Now remove rev {} for {}", INITIATION, tunnelId);
               tearDownPseudoWireInit(
                       tunnelId,
                       oldPw.l2TunnelPolicy().cP2(),
                       revTermNextFuture,
                       REV
               );

           }
        });
        fwdTermNextFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("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("Rev {} removed. Now remove rev {} for {}", INITIATION, TERMINATION, tunnelId);
                tearDownPseudoWireTerm(
                        oldPw.l2Tunnel(),
                        oldPw.l2TunnelPolicy().cP1(),
                        revPwFuture,
                        REV
                );
            }
        });
        // At the end we install the new pw.
        fwdPwFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Deploying new fwd pw for {}", tunnelId);
                Result lamdaResult = deployPseudoWireInit(
                        newPw.l2Tunnel(),
                        newPw.l2TunnelPolicy().cP1(),
                        newPw.l2TunnelPolicy().cP2(),
                        FWD
                );
                if (lamdaResult != SUCCESS) {
                    return;
                }
                lamdaResult = deployPolicy(
                        tunnelId,
                        newPw.l2TunnelPolicy().cP1(),
                        newPw.l2TunnelPolicy().cP1InnerTag(),
                        newPw.l2TunnelPolicy().cP1OuterTag(),
                        lamdaResult.nextId
                );
                if (lamdaResult != SUCCESS) {
                    return;
                }
                deployPseudoWireTerm(
                        newPw.l2Tunnel(),
                        newPw.l2TunnelPolicy().cP2(),
                        newPw.l2TunnelPolicy().cP2OuterTag(),
                        FWD
                );

            }
        });
        revPwFuture.thenAcceptAsync(status -> {
            if (status == null) {
                log.debug("Deploying new rev pw for {}", tunnelId);
                Result lamdaResult = deployPseudoWireInit(
                        newPw.l2Tunnel(),
                        newPw.l2TunnelPolicy().cP2(),
                        newPw.l2TunnelPolicy().cP1(),
                        REV
                );
                if (lamdaResult != SUCCESS) {
                    return;
                }
                lamdaResult = deployPolicy(
                        tunnelId,
                        newPw.l2TunnelPolicy().cP2(),
                        newPw.l2TunnelPolicy().cP2InnerTag(),
                        newPw.l2TunnelPolicy().cP2OuterTag(),
                        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("Processing Pwaas CONFIG_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 to handle the pw removal.
     *
     * @param pwToRemove the pseudo wires to remove
     */
    private void tearDown(Set<DefaultL2TunnelDescription> pwToRemove) {
        Result result;
        long l2TunnelId;
        // We remove all the pw in the configuration file.
        for (DefaultL2TunnelDescription currentL2Tunnel : pwToRemove) {
            l2TunnelId = currentL2Tunnel.l2Tunnel().tunnelId();
            if (l2TunnelId == 0) {
                log.warn("Tunnel id cannot be 0");
                continue;
            }
            result = verifyPseudoWire(currentL2Tunnel);
            if (result != SUCCESS) {
                continue;
            }
            // First all we have to delete the policy.
            deletePolicy(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    currentL2Tunnel.l2TunnelPolicy().cP1InnerTag(),
                    currentL2Tunnel.l2TunnelPolicy().cP1OuterTag(),
                    null,
                    FWD
            );
            // Finally we will tear down the pseudo wire.
            tearDownPseudoWireInit(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    null,
                    FWD
            );
            tearDownPseudoWireTerm(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    null,
                    FWD
            );
            // We do the same operations on the reverse side.
            deletePolicy(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    currentL2Tunnel.l2TunnelPolicy().cP2InnerTag(),
                    currentL2Tunnel.l2TunnelPolicy().cP2OuterTag(),
                    null,
                    REV
            );
            tearDownPseudoWireInit(
                    l2TunnelId,
                    currentL2Tunnel.l2TunnelPolicy().cP2(),
                    null,
                    REV
            );
            tearDownPseudoWireTerm(
                    currentL2Tunnel.l2Tunnel(),
                    currentL2Tunnel.l2TunnelPolicy().cP1(),
                    null,
                    REV
            );
        }

    }

    /**
     * Helper method to verify the integrity of the pseudo wire.
     *
     * @param l2TunnelDescription the pseudo wire description
     * @return the result of the check
     */
    private Result verifyPseudoWire(DefaultL2TunnelDescription l2TunnelDescription) {
        Result result;
        DefaultL2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
        DefaultL2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();
        result = verifyTunnel(l2Tunnel);
        if (result != SUCCESS) {
            log.warn("Tunnel {}: did not pass the validation", l2Tunnel.tunnelId());
            return result;
        }
        result = verifyPolicy(
                l2TunnelPolicy.isAllVlan(),
                l2TunnelPolicy.cP1InnerTag(),
                l2TunnelPolicy.cP1OuterTag(),
                l2TunnelPolicy.cP2InnerTag(),
                l2TunnelPolicy.cP2OuterTag()
        );
        if (result != SUCCESS) {
            log.warn("Policy for tunnel {}: did not pass the validation", l2Tunnel.tunnelId());
            return result;
        }

        return SUCCESS;
    }

    /**
     * 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
     * @return the result of the operation
     */
    private Result deployPolicy(long tunnelId,
                                ConnectPoint ingress,
                                VlanId ingressInner,
                                VlanId ingressOuter,
                                int nextId) {
        if (!srManager.mastershipService.isLocalMaster(ingress.deviceId())) {
            log.info("Abort creation of policy for tunnel {}: I am not the master", tunnelId);
            return SUCCESS;
        }
        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);
        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;
    }

    /**
     * Helper method to verify if the policy is whether or not
     * supported.
     *
     * @param isAllVlan all vlan mode
     * @param ingressInner the ingress inner tag
     * @param ingressOuter the ingress outer tag
     * @param egressInner the egress inner tag
     * @param egressOuter the egress outer tag
     * @return the result of verification
     */
    private Result verifyPolicy(boolean isAllVlan,
                                VlanId ingressInner,
                                VlanId ingressOuter,
                                VlanId egressInner,
                                VlanId egressOuter) {
        // AllVlan mode is not supported yet.
        if (isAllVlan) {
            log.warn("AllVlan not supported yet");
            return UNSUPPORTED;
        }
        // The vlan tags for cP1 and cP2 have to be different from
        // vlan none.
        if (ingressInner.equals(VlanId.NONE) ||
                ingressOuter.equals(VlanId.NONE) ||
                egressInner.equals(VlanId.NONE) ||
                egressOuter.equals(VlanId.NONE)) {
            log.warn("The vlan tags for the connect point have to be" +
                             "different from vlan none");
            return WRONG_PARAMETERS;
        }
        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) {
        if (!srManager.mastershipService.isLocalMaster(ingress.deviceId())) {
            log.info("Abort initiation of tunnel {}: I am not the master", l2Tunnel.tunnelId());
            return SUCCESS;
        }
        // We need at least a path between ingress and egress.
        Link nextHop = getNextHop(ingress, egress);
        if (nextHop == null) {
            log.warn("No path between ingress and egress");
            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.
        // It's fine to abort the termination if we are
        // not the master.
        if (!srManager.mastershipService.isLocalMaster(egress.deviceId())) {
            log.info("Abort termination of tunnel {}: I am not the master", l2Tunnel.tunnelId());
            return SUCCESS;
        }
        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;

    }

    /**
     * Helper method to verify if the tunnel is whether or not
     * supported.
     *
     * @param l2Tunnel the tunnel to verify
     * @return the result of the verification
     */
    private Result verifyTunnel(DefaultL2Tunnel l2Tunnel) {
        // Service delimiting tag not supported yet.
        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
            log.warn("Service delimiting tag not supported yet");
            return UNSUPPORTED;
        }
        // Tag mode not supported yet.
        if (l2Tunnel.pwMode() == TAGGED) {
            log.warn("Tagged mode not supported yet");
            return UNSUPPORTED;
        }
        // Raw mode without service delimiting tag
        // is the only mode supported for now.
        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) {
        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
            // using the egress leaf device id.
            MplsLabel srLabel;
            try {
                 srLabel = MplsLabel.mplsLabel(
                         srManager.deviceConfiguration().getIPv4SegmentId(egressId)
                 );
            } catch (DeviceConfigNotFoundException e) {
                log.warn("Sr label 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;
    }

    /**
     * Returns the next hop.
     *
     * @param srcCp the ingress connect point
     * @param dstCp the egress connect point
     * @return the next hop
     */
    private Link getNextHop(ConnectPoint srcCp, ConnectPoint dstCp) {
        // We retrieve a set of disjoint paths.
        Set<DisjointPath> paths = srManager.pathService.getDisjointPaths(
                srcCp.elementId(),
                dstCp.elementId()
        );
        // We randmly pick a path.
        if (paths.isEmpty()) {
            return null;
        }
        int size = paths.size();
        int index = RandomUtils.nextInt(0, size);
        // We verify if the path is ok and there is not
        // a misconfiguration.
        List<Link> links = Iterables.get(paths, index).links();
        checkState(links.size() == 2, WRONG_TOPOLOGY, links);
        return links.get(0);
    }

    /**
     * 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,
                              CompletableFuture<ObjectiveError> future,
                              Direction direction) {
        if (!srManager.mastershipService.isLocalMaster(ingress.deviceId())) {
            log.info("Abort delete of policy for tunnel {}: I am not the master", tunnelId);
            if (future != null) {
                future.complete(null);
            }
            return;
        }
        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);
        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 (!srManager.mastershipService.isLocalMaster(ingress.deviceId())) {
            log.info("Abort delete of {} for {}: I am not the master", INITIATION, key);
            if (future != null) {
                future.complete(null);
            }
            return;
        }
        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();
        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));
        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) {
        /*
         * We verify the mastership for the termination.
         */
        String key = generateKey(l2Tunnel.tunnelId(), direction);
        if (!srManager.mastershipService.isLocalMaster(egress.deviceId())) {
            log.info("Abort delete of {} for {}: I am not the master", TERMINATION, key);
            if (future != null) {
                future.complete(null);
            }
            return;
        }
        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));

        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));
        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 the outcomes of an operation.
     */
    public enum Result {
        /**
         * Happy ending scenario it has been created.
         */
        SUCCESS(0, "It has been Created"),
        /**
         * We have problems with the supplied parameters.
         */
        WRONG_PARAMETERS(1, "Wrong parameters"),
        /**
         * It already exists.
         */
        ID_EXISTS(2, "The id already exists"),
        /**
         * We have an internal error during the deployment
         * phase.
         */
        INTERNAL_ERROR(3, "Internal error"),
        /**
         * The operation is not supported.
         */
        UNSUPPORTED(4, "Unsupported");

        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
    }

}
