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

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableSet;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.config.Config;
import org.onosproject.net.device.DeviceService;
import org.onosproject.net.intf.InterfaceService;
import org.onosproject.segmentrouting.pwaas.L2Tunnel;
import org.onosproject.segmentrouting.pwaas.L2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.L2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.DefaultL2Tunnel;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelDescription;
import org.onosproject.segmentrouting.pwaas.DefaultL2TunnelPolicy;
import org.onosproject.segmentrouting.pwaas.L2Mode;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * App configuration object for Pwaas.
 */
public class PwaasConfig extends Config<ApplicationId> {

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    public DeviceService deviceService;

    @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
    public InterfaceService intfService;

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

    private static final String SRC_CP = "cP1";
    private static final String DST_CP = "cP2";
    private static final String SRC_OUTER_TAG = "cP1OuterTag";
    private static final String DST_OUTER_TAG = "cP2OuterTag";
    private static final String SRC_INNER_TAG = "cP1InnerTag";
    private static final String DST_INNER_TAG = "cP2InnerTag";
    private static final String MODE = "mode";
    private static final String SD_TAG = "sdTag";
    private static final String PW_LABEL = "pwLabel";

    public PwaasConfig(DeviceService devS, InterfaceService intfS) {

        super();

        deviceService = devS;
        intfService = intfS;
    }

    public PwaasConfig() {

        super();

        deviceService = AbstractShellCommand.get(DeviceService.class);
        intfService = AbstractShellCommand.get(InterfaceService.class);
    }
    /**
     * Error message for missing parameters.
     */
    private static final String MISSING_PARAMS = "Missing parameters in pseudo wire description";

    /**
     * Error message for invalid l2 mode.
     */
    private static final String INVALID_L2_MODE = "Invalid pseudo wire mode";

    /**
     * Error message for invalid VLAN.
     */
    private static final String INVALID_VLAN = "Vlan should be either int or */-";

    /**
     * Error message for invalid PW label.
     */
    private static final String INVALID_PW_LABEL = "Pseudowire label should be an integer";

    /**
     * Verify if the pwaas configuration block is valid.
     *
     * Here we try to ensure that the provided pseudowires will get instantiated
     * correctly in the network. We also check for any collisions with already used
     * interfaces and also between different pseudowires. Most of the restrictions stem
     * from the fact that all vlan matching is done in table 10 of ofdpa.
     *
     * @return true, if the configuration block is valid.
     *         False otherwise.
     */
    @Override
    public boolean isValid() {

        Set<L2TunnelDescription> pseudowires;
        try {
            pseudowires = getPwIds().stream()
                    .map(this::getPwDescription)
                    .collect(Collectors.toSet());

            // check semantics now and return
            return configurationValidity(pseudowires);

        } catch (IllegalArgumentException e) {
            log.warn("{}", e.getMessage());
            return false;
        }
    }

    /**
     * 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 void verifyTunnel(L2Tunnel l2Tunnel) {

        // Service delimiting tag not supported yet.
        if (!l2Tunnel.sdTag().equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.format("Service delimiting tag not supported yet for " +
                                                             "pseudowire %d.", l2Tunnel.tunnelId()));
        }

        // Tag mode not supported yet.
        if (l2Tunnel.pwMode() == L2Mode.TAGGED) {
            throw new IllegalArgumentException(String.format("Tagged mode not supported yet for pseudowire %d.",
                                                                            l2Tunnel.tunnelId()));
        }

        // Raw mode without service delimiting tag
        // is the only mode supported for now.
    }

    /**
     * Helper method to verify if the policy is whether or not
     * supported and if policy will be successfully instantiated in the
     * network.
     *
     * @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 void verifyPolicy(ConnectPoint cP1,
                              ConnectPoint cP2,
                              VlanId ingressInner,
                              VlanId ingressOuter,
                              VlanId egressInner,
                              VlanId egressOuter,
                              Long tunnelId) {

        if (cP1.deviceId().equals(cP2.deviceId())) {
            throw new IllegalArgumentException(String.format("Pseudowire connection points can not reside in the " +
                                                             "same node, in pseudowire %d.", tunnelId));
        }

        // We can have multiple tags, all of them can be NONE,
        // indicating untagged traffic, however, the outer tag can
        // not have value if the inner tag is None
        if (ingressInner.equals(VlanId.NONE) && !ingressOuter.equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.format("Inner tag should not be empty when " +
                                                             "outer tag is set for pseudowire %d for cP1.",
                                                              tunnelId));
        }

        if (egressInner.equals(VlanId.NONE) && !egressOuter.equals(VlanId.NONE)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Inner tag should not be empty when" +
                                                                            " outer tag is set for pseudowire %d " +
                                                                            "for cP2.", tunnelId)));
        }

        if (ingressInner.equals(VlanId.ANY) ||
                ingressOuter.equals(VlanId.ANY) ||
                egressInner.equals(VlanId.ANY) ||
                egressOuter.equals(VlanId.ANY)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Wildcard VLAN matching not yet " +
                                                                            "supported for pseudowire %d.",
                                                                            tunnelId)));
        }

        if (((!ingressOuter.equals(VlanId.NONE) && !ingressInner.equals(VlanId.NONE)) &&
                (egressOuter.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE)))
                || ((ingressOuter.equals(VlanId.NONE) && ingressInner.equals(VlanId.NONE)) &&
                (!egressOuter.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE)))) {
            throw new IllegalArgumentException(String.valueOf(String.format("Support for double tag <-> untag is not" +
                                                                                    "supported for pseudowire %d.",
                                                                            tunnelId)));
        }
        if ((!ingressInner.equals(VlanId.NONE) &&
                ingressOuter.equals(VlanId.NONE) &&
                !egressOuter.equals(VlanId.NONE))
           || (egressOuter.equals(VlanId.NONE) &&
                !egressInner.equals(VlanId.NONE) &&
                !ingressOuter.equals(VlanId.NONE))) {
                throw new IllegalArgumentException(String.valueOf(String.format("Support for double-tag<->" +
                                                                                "single-tag is not supported" +
                                                                                " for pseudowire %d.", tunnelId)));
        }

        if ((ingressInner.equals(VlanId.NONE) && !egressInner.equals(VlanId.NONE))
                || (!ingressInner.equals(VlanId.NONE) && egressInner.equals(VlanId.NONE))) {
            throw new IllegalArgumentException(String.valueOf(String.format("single-tag <-> untag is not supported" +
                                                                            " for pseudowire %d.", tunnelId)));
        }


        if (!ingressInner.equals(egressInner) && !ingressOuter.equals(egressOuter)) {
            throw new IllegalArgumentException(String.valueOf(String.format("We do not support changing both tags " +
                                                                             "in double tagged pws, only the outer," +
                                                                             " for pseudowire %d.", tunnelId)));
        }

        // check if cp1 and port of cp1 exist
        if (deviceService.getDevice(cP1.deviceId()) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("cP1 device %s does not exist for" +
                                                                            " pseudowire %d.", cP1.deviceId(),
                                                                            tunnelId)));
        }

        if (deviceService.getPort(cP1) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP1 device %s does not" +
                                                                            " exist for pseudowire %d.", cP1.port(),
                                                                            cP1.deviceId(), tunnelId)));
        }

        // check if cp2 and port of cp2 exist
        if (deviceService.getDevice(cP2.deviceId()) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("cP2 device %s does not exist for" +
                                                                            " pseudowire %d.", cP2.deviceId(),
                                                                            tunnelId)));
        }

        if (deviceService.getPort(cP2) == null) {
            throw new IllegalArgumentException(String.valueOf(String.format("Port %s for cP2 device %s does " +
                                                                            "not exist for pseudowire %d.",
                                                                            cP2.port(), cP2.deviceId(), tunnelId)));
        }
    }

    /**
     * Verifies that the pseudowires will not conflict with each other.
     *
     * Further, check if vlans for connect points are already used.
     *
     * @param tunnel Tunnel for pw
     * @param policy Policy for pw
     * @param labelSet Label set used so far with this configuration
     * @param vlanSet Vlan set used with this configuration
     * @param tunnelSet Tunnel set used with this configuration
     */
    private void verifyGlobalValidity(L2Tunnel tunnel,
                                      L2TunnelPolicy policy,
                                      Set<MplsLabel> labelSet,
                                      Map<ConnectPoint, Set<VlanId>> vlanSet,
                                      Set<Long> tunnelSet) {

        if (tunnelSet.contains(tunnel.tunnelId())) {
            throw new IllegalArgumentException(String.valueOf(String.format("Tunnel Id %d already used by" +
                                                                           " another pseudowire, in " +
                                                                           "pseudowire %d!", tunnel.tunnelId(),
                                                                            tunnel.tunnelId())));
        }
        tunnelSet.add(tunnel.tunnelId());

        // check if tunnel id is used again
        ConnectPoint cP1 = policy.cP1();
        ConnectPoint cP2 = policy.cP2();

        // insert cps to hashmap if this is the first time seen
        if (!vlanSet.containsKey(cP1)) {
            vlanSet.put(cP1, new HashSet<VlanId>());
        }
        if (!vlanSet.containsKey(cP2)) {
            vlanSet.put(cP2, new HashSet<VlanId>());
        }

        // if single tagged or untagged vlan is the inner
        // if double tagged vlan is the outer
        VlanId vlanToCheckCP1;
        if (policy.cP1OuterTag().equals(VlanId.NONE)) {
            vlanToCheckCP1 = policy.cP1InnerTag();
        } else {
            vlanToCheckCP1 = policy.cP1OuterTag();
        }

        VlanId vlanToCheckCP2;
        if (policy.cP2OuterTag().equals(VlanId.NONE)) {
            vlanToCheckCP2 = policy.cP2InnerTag();
        } else {
            vlanToCheckCP2 = policy.cP2OuterTag();
        }

        if (labelSet.contains(tunnel.pwLabel())) {
            throw new IllegalArgumentException(String.valueOf(String.format("Label %s already used by another" +
                                                                            " pseudowire, in pseudowire %d!",
                                                                            tunnel.pwLabel(), tunnel.tunnelId())));
        }
        labelSet.add(tunnel.pwLabel());

        if (vlanSet.get(cP1).contains(vlanToCheckCP1)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already used " +
                                                                            "by another pseudowire, in pseudowire" +
                                                                            " %d!", vlanToCheckCP1,  cP1,
                                                                            tunnel.tunnelId())));
        }
        vlanSet.get(cP1).add(vlanToCheckCP1);

        if (vlanSet.get(cP2).contains(vlanToCheckCP2)) {
            throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already used" +
                                                                            " by another pseudowire, in" +
                                                                            " pseudowire %d!", vlanToCheckCP2, cP2,
                                                                            tunnel.tunnelId())));
        }
        vlanSet.get(cP2).add(vlanToCheckCP2);

        // check that vlans for the connect points are not used
        intfService.getInterfacesByPort(cP1).stream()
                .forEach(intf -> {

                    // check if tagged pw affects tagged interface
                    if (intf.vlanTagged().contains(vlanToCheckCP1)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP1 %s already" +
                                                                                        " used for this interface, in" +
                                                                                        " pseudowire %d!",
                                                                                        vlanToCheckCP1, cP1,
                                                                                        tunnel.tunnelId())));
                    }

                    // if vlanNative != null this interface is configured with untagged traffic also
                    // check if it collides with untagged interface
                    if ((intf.vlanNative() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP1 " +
                                                                                         "%s already used for this " +
                                                                                         "interface, in pseudowire " +
                                                                                         "%d!", cP1,
                                                                                         tunnel.tunnelId())));
                    }

                    // if vlanUntagged != null this interface is configured only with untagged traffic
                    // check if it collides with untagged interface
                    if ((intf.vlanUntagged() != null) && vlanToCheckCP1.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for " +
                                                                                         "cP1 %s already" +
                                                                                         " used for this interface," +
                                                                                         " in pseudowire %d!",
                                                                                         cP1, tunnel.tunnelId())));
                    }
                });

        intfService.getInterfacesByPort(cP2).stream()
                .forEach(intf -> {
                    if (intf.vlanTagged().contains(vlanToCheckCP2)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Vlan '%s' for cP2 %s already" +
                                                                                        " used for  this interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        vlanToCheckCP2, cP2,
                                                                                        tunnel.tunnelId())));
                    }

                    // if vlanNative != null this interface is configured with untagged traffic also
                    // check if it collides with untagged interface
                    if ((intf.vlanNative() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s " +
                                                                                        "already used for this" +
                                                                                        " interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        cP2, tunnel.tunnelId())));
                    }

                    // if vlanUntagged != null this interface is configured only with untagged traffic
                    // check if it collides with untagged interface
                    if ((intf.vlanUntagged() != null) && vlanToCheckCP2.equals(VlanId.NONE)) {
                        throw new IllegalArgumentException(String.valueOf(String.format("Untagged traffic for cP2 %s" +
                                                                                        " already" +
                                                                                        " used for this interface, " +
                                                                                        "in pseudowire %d!",
                                                                                        cP2, tunnel.tunnelId())));
                    }
                });

    }

    /**
     * Helper method to verify the integrity of the pseudo wire.
     *
     * @param l2TunnelDescription the pseudo wire description
     * @return the result of the check
     */
    private void verifyPseudoWire(L2TunnelDescription l2TunnelDescription,
                                  Set<MplsLabel> labelSet,
                                  Map<ConnectPoint, Set<VlanId>> vlanset,
                                  Set<Long> tunnelSet) {

        L2Tunnel l2Tunnel = l2TunnelDescription.l2Tunnel();
        L2TunnelPolicy l2TunnelPolicy = l2TunnelDescription.l2TunnelPolicy();

        verifyTunnel(l2Tunnel);

        verifyPolicy(
                l2TunnelPolicy.cP1(),
                l2TunnelPolicy.cP2(),
                l2TunnelPolicy.cP1InnerTag(),
                l2TunnelPolicy.cP1OuterTag(),
                l2TunnelPolicy.cP2InnerTag(),
                l2TunnelPolicy.cP2OuterTag(),
                l2Tunnel.tunnelId()
        );

        verifyGlobalValidity(l2Tunnel,
                             l2TunnelPolicy,
                             labelSet,
                             vlanset,
                             tunnelSet);

    }

    /**
     * Checks if the configured pseudowires will create problems in the network.
     * If yes, then no pseudowires is deployed from this configuration.
     *
     * @param pseudowires Set of pseudowries to validate
     * @return returns true if everything goes well.
     */
    public boolean configurationValidity(Set<L2TunnelDescription> pseudowires) {

        // structures to keep pw information
        // in order to see if instantiating them will create
        // problems
        Set<Long> tunIds = new HashSet<>();
        Set<MplsLabel> labelsUsed = new HashSet<>();
        Map<ConnectPoint, Set<VlanId>> vlanIds = new HashMap<>();

        // check that pseudowires can be instantiated in the network
        // we try to guarantee that all the pws will work before
        // instantiating any of them
        for (L2TunnelDescription pw : pseudowires) {
            verifyPseudoWire(pw, labelsUsed, vlanIds, tunIds);
        }

        return true;
    }

    /**
     * Returns all pseudo wire keys.
     *
     * @return all keys (tunnels id)
     * @throws IllegalArgumentException if wrong format
     */
    public Set<Long> getPwIds() {
        ImmutableSet.Builder<Long> builder = ImmutableSet.builder();
        object.fields().forEachRemaining(entry -> {
            Long tunnelId = Long.parseLong(entry.getKey());
            builder.add(tunnelId);
        });
        return builder.build();
    }

    /**
     * Parses a vlan as a string. Returns the VlanId if
     * provided String can be parsed as an integer or is '' / '*'
     *
     * @param vlan string as read from configuration
     * @return VlanId
     * @throws IllegalArgumentException if wrong format of vlan
     */
    public VlanId parseVlan(String vlan) {

        if (vlan.equals("*") || vlan.equals("Any")) {
            return VlanId.vlanId("Any");
        } else if (vlan.equals("") || vlan.equals("None")) {
            return VlanId.vlanId("None");
        } else {
            try {
                VlanId newVlan = VlanId.vlanId(vlan);
                return newVlan;
            } catch (IllegalArgumentException e) {
                throw new IllegalArgumentException(INVALID_VLAN);
            }
        }
    }

    /**
     *
     * @param mode RAW or TAGGED
     * @return the L2Mode if input is correct
     * @throws  IllegalArgumentException if not supported mode
     */
    public L2Mode parseMode(String mode) {

        if (!mode.equals("RAW") && !mode.equals("TAGGED")) {
            throw  new IllegalArgumentException(INVALID_L2_MODE);
        }

        return L2Mode.valueOf(mode);
    }

    /**
     *
     * @param label the mpls label of the pseudowire
     * @return the MplsLabel
     * @throws IllegalArgumentException if label is invalid
     */
    public MplsLabel parsePWLabel(String label) {

        try {
            MplsLabel pwLabel = MplsLabel.mplsLabel(label);
            return pwLabel;
        } catch (Exception e) {
            throw new IllegalArgumentException(INVALID_PW_LABEL);
        }
    }

    /**
     * Returns pw description of given pseudo wire id.
     *
     * @param tunnelId pseudo wire key
     * @return set of l2 tunnel descriptions
     * @throws IllegalArgumentException if wrong format
     */
    public L2TunnelDescription getPwDescription(Long tunnelId) {
        JsonNode pwDescription = object.get(tunnelId.toString());
        if (!hasFields((ObjectNode) pwDescription,
                      SRC_CP, SRC_INNER_TAG, SRC_OUTER_TAG,
                      DST_CP, DST_INNER_TAG, DST_OUTER_TAG,
                      MODE, SD_TAG, PW_LABEL)) {
            throw new IllegalArgumentException(MISSING_PARAMS);
        }
        String tempString;

        tempString = pwDescription.get(SRC_CP).asText();
        ConnectPoint srcCp = ConnectPoint.deviceConnectPoint(tempString);

        tempString = pwDescription.get(DST_CP).asText();
        ConnectPoint dstCp = ConnectPoint.deviceConnectPoint(tempString);

        tempString = pwDescription.get(SRC_INNER_TAG).asText();
        VlanId srcInnerTag = parseVlan(tempString);

        tempString = pwDescription.get(SRC_OUTER_TAG).asText();
        VlanId srcOuterTag = parseVlan(tempString);

        tempString = pwDescription.get(DST_INNER_TAG).asText();
        VlanId dstInnerTag = parseVlan(tempString);

        tempString = pwDescription.get(DST_OUTER_TAG).asText();
        VlanId dstOuterTag = parseVlan(tempString);

        tempString = pwDescription.get(MODE).asText();
        L2Mode l2Mode = parseMode(tempString);

        tempString = pwDescription.get(SD_TAG).asText();
        VlanId sdTag = parseVlan(tempString);

        tempString = pwDescription.get(PW_LABEL).asText();
        MplsLabel pwLabel = parsePWLabel(tempString);

        L2Tunnel l2Tunnel = new DefaultL2Tunnel(
                l2Mode,
                sdTag,
                tunnelId,
                pwLabel
        );

        L2TunnelPolicy l2TunnelPolicy = new DefaultL2TunnelPolicy(
                tunnelId,
                srcCp,
                srcInnerTag,
                srcOuterTag,
                dstCp,
                dstInnerTag,
                dstOuterTag
        );

        return new DefaultL2TunnelDescription(l2Tunnel, l2TunnelPolicy);
    }

    /**
     * Removes a pseudowire from the configuration tree.
     * @param pwId Pseudowire id
     * @return null if pwId did not exist, or the object representing the
     * udpated configuration tree
     */
    public ObjectNode removePseudowire(String pwId) {

        JsonNode value = object.remove(pwId);
        if (value == null) {
            return (ObjectNode) value;
        } else {
            return object;
        }
    }

    /**
     * Adds a pseudowire to the configuration tree of pwwas. It also checks
     * if the configuration is valid, if not return null and does not add the node,
     * if yes return the new configuration. Caller will propagate update events.
     *
     * If the pseudowire already exists in the configuration it gets updated.
     *
     * @param tunnelId Id of tunnel
     * @param pwLabel PW label of tunnel
     * @param cP1 Connection point 1
     * @param cP1InnerVlan Inner vlan of cp1
     * @param cP1OuterVlan Outer vlan of cp2
     * @param cP2 Connection point 2
     * @param cP2InnerVlan Inner vlan of cp2
     * @param cP2OuterVlan Outer vlan of cp2
     * @param mode Mode for the pw
     * @param sdTag Service delimiting tag for the pw
     * @return The ObjectNode config if configuration is valid with the new pseudowire
     * or null.
     */
    public ObjectNode addPseudowire(String tunnelId, String pwLabel, String cP1,
                                    String cP1InnerVlan, String cP1OuterVlan, String cP2,
                                    String cP2InnerVlan, String cP2OuterVlan,
                                    String mode, String sdTag) {


        ObjectNode newPw = new ObjectNode(JsonNodeFactory.instance);

        // add fields for pseudowire
        newPw.put(SRC_CP, cP1);
        newPw.put(DST_CP, cP2);
        newPw.put(PW_LABEL, pwLabel);
        newPw.put(SRC_INNER_TAG, cP1InnerVlan);
        newPw.put(SRC_OUTER_TAG, cP1OuterVlan);
        newPw.put(DST_INNER_TAG, cP2InnerVlan);
        newPw.put(DST_OUTER_TAG, cP2OuterVlan);
        newPw.put(SD_TAG, sdTag);
        newPw.put(MODE, mode);

        object.set(tunnelId, newPw);

        if (!isValid()) {
            log.info("Pseudowire could not be created : {}");
            object.remove(tunnelId);
            return null;
        }

        return object;
    }
}
