/*
 * Copyright 2015-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.web;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import javafx.util.Pair;
import org.onlab.packet.MplsLabel;
import org.onlab.packet.VlanId;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.ConnectPoint;
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.List;

import static org.onosproject.segmentrouting.pwaas.PwaasUtil.*;

/**
 * Codec of PseudowireCodec class.
 */
public final class PseudowireCodec extends JsonCodec<DefaultL2TunnelDescription> {

    // JSON field names
    private static final String PW_ID = "pwId";
    private static final String CP1 = "cP1";
    private static final String CP2 = "cP2";
    private static final String CP1_INNER_TAG = "cP1InnerTag";
    private static final String CP1_OUTER_TAG = "cP1OuterTag";
    private static final String CP2_INNER_TAG = "cP2InnerTag";
    private static final String CP2_OUTER_TAG = "cP2OouterTag";
    private static final String MODE = "mode";
    private static final String SERVICE_DELIM_TAG = "serviceTag";
    private static final String PW_LABEL = "pwLabel";

    // JSON field names for error in return
    private static final String FAILED_PWS = "failedPws";
    private static final String FAILED_PW = "pw";
    private static final String REASON = "reason";

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

    @Override
    public ObjectNode encode(DefaultL2TunnelDescription pseudowire, CodecContext context) {
        final ObjectNode result = context.mapper().createObjectNode()
                .put(PW_ID, pseudowire.l2Tunnel().tunnelId());

        result.put(CP1, pseudowire.l2TunnelPolicy().cP1().toString());
        result.put(CP2, pseudowire.l2TunnelPolicy().cP2().toString());

        result.put(CP1_INNER_TAG, pseudowire.l2TunnelPolicy().cP1InnerTag().toString());
        result.put(CP1_OUTER_TAG, pseudowire.l2TunnelPolicy().cP1OuterTag().toString());


        result.put(CP2_INNER_TAG, pseudowire.l2TunnelPolicy().cP2InnerTag().toString());
        result.put(CP2_OUTER_TAG, pseudowire.l2TunnelPolicy().cP2OuterTag().toString());

        result.put(MODE, pseudowire.l2Tunnel().pwMode() == L2Mode.RAW ? "RAW" : "TAGGED");
        result.put(SERVICE_DELIM_TAG, pseudowire.l2Tunnel().sdTag().toString());
        result.put(PW_LABEL, pseudowire.l2Tunnel().pwLabel().toString());

        return result;
    }

    /**
     * Encoded in an Object Node the pseudowire and the specificError it failed.
     *
     * @param failedPW The failed pseudowire
     * @param specificError The specificError it failed
     * @param context Our context
     * @return A node containing the information we provided
     */
    public ObjectNode encodeError(DefaultL2TunnelDescription failedPW, String specificError,
                                          CodecContext context) {
        ObjectNode result = context.mapper().createObjectNode();

        ObjectNode pw = encode(failedPW, context);
        result.set(FAILED_PW, pw);
        result.put(REASON, specificError);

        return result;
    }

    /**
     * Returns a JSON containing the failed pseudowires and the reason that its one failed.
     *
     * @param failedPws Pairs of pws and reasons.
     * @param context The context
     * @return ObjectNode representing the json to return
     */
    public ObjectNode encodeFailedPseudowires(
            List<Pair<DefaultL2TunnelDescription, String>> failedPws,
            CodecContext context) {

        ArrayNode failedNodes = context.mapper().createArrayNode();
        failedPws.stream()
                .forEach(failed -> failedNodes.add(encodeError(failed.getKey(), failed.getValue(), context)));
        final ObjectNode toReturn = context.mapper().createObjectNode();
        toReturn.set(FAILED_PWS, failedNodes);
        return toReturn;
    }

    /**
     * Decodes a json containg a single field with the pseudowire id.
     *
     * @param json Json to decode.
     * @return The pseudowire id.
     */
    public static Integer decodeId(ObjectNode json) {

        Integer id = parsePwId(json.path(PW_ID).asText());
        if (id == null) {
            log.error("Pseudowire id is not an integer!");
            return null;
        }

        return id;
    }

    @Override
    public DefaultL2TunnelDescription decode(ObjectNode json, CodecContext context) {

        String tempString;

        Integer id = parsePwId(json.path(PW_ID).asText());
        if (id == null) {
            log.error("Pseudowire id is not an integer");
            return null;
        }

        ConnectPoint cP1, cP2;
        try {
            tempString = json.path(CP1).asText();
            cP1 = ConnectPoint.deviceConnectPoint(tempString);
        } catch (Exception e) {
            log.error("cP1 is not a valid connect point!");
            return null;
        }

        try {
            tempString = json.path(CP2).asText();
            cP2 = ConnectPoint.deviceConnectPoint(tempString);
        } catch (Exception e) {
            log.error("cP2 is not a valid connect point!");
            return null;
        }

        VlanId cP1InnerVlan = parseVlan(json.path(CP1_INNER_TAG).asText());
        VlanId cP1OuterVlan = parseVlan(json.path(CP1_OUTER_TAG).asText());
        VlanId cP2InnerVlan = parseVlan(json.path(CP2_INNER_TAG).asText());
        VlanId cP2OuterVlan = parseVlan(json.path(CP2_OUTER_TAG).asText());
        if ((cP1InnerVlan == null) || (cP1OuterVlan == null) ||
                (cP2InnerVlan == null) || (cP2OuterVlan == null)) {
            log.error("One or more vlan for cp1 or cp2 is malformed, it shouldbe an integer / Any / None / *");
            return null;
        }

        L2Mode mode = parseMode(json.path(MODE).asText());
        if (mode == null) {
            log.error("Mode should be RAW or TAGGED!");
            return null;
        }

        VlanId sdTag = parseVlan(json.path(SERVICE_DELIM_TAG).asText());
        if (sdTag == null) {
            log.error("SD tag is malformed, it should be an integer / Any / None / *");
            return null;
        }

        MplsLabel pwLabel = parsePWLabel(json.path(PW_LABEL).asText());
        if (pwLabel == null) {
            log.error("PW label is malformed, should be an integer!");
            return null;
        }

        DefaultL2Tunnel l2Tunnel;
        DefaultL2TunnelPolicy l2Policy;

        l2Tunnel = new DefaultL2Tunnel(mode, sdTag, id, pwLabel);
        l2Policy = new DefaultL2TunnelPolicy(id, cP1, cP1InnerVlan, cP1OuterVlan,
                                             cP2, cP2InnerVlan, cP2OuterVlan);

        return new DefaultL2TunnelDescription(l2Tunnel, l2Policy);

    }
}
