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

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onosproject.net.Link.State.ACTIVE;
import static org.onosproject.net.Link.Type.DIRECT;

import com.fasterxml.jackson.databind.node.ArrayNode;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;

import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultLink;
import org.onosproject.net.DeviceId;
import org.onosproject.net.NetworkResource;
import org.onosproject.net.PortNumber;
import org.onosproject.net.provider.ProviderId;
import org.onosproject.pce.pceservice.ExplicitPathInfo;
import org.onosproject.pce.pceservice.PcePath;
import org.onosproject.pce.pceservice.DefaultPcePath;
import org.onosproject.pce.pceservice.constraint.CostConstraint;
import org.onosproject.pce.pceservice.constraint.PceBandwidthConstraint;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.databind.node.ObjectNode;
import com.fasterxml.jackson.databind.JsonNode;

import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;

/**
 * PCE path json codec.
 */
public final class PcePathCodec extends JsonCodec<PcePath> {
    private final Logger log = LoggerFactory.getLogger(PcePathCodec.class);
    private static final String SOURCE = "source";
    private static final String DESTINATION = "destination";
    private static final String LSP_TYPE = "pathType";
    private static final String SYMBOLIC_PATH_NAME = "name";
    private static final String CONSTRAINT = "constraint";
    private static final String COST = "cost";
    private static final String BANDWIDTH = "bandwidth";
    private static final String PATH_ID = "pathId";
    private static final String EXPLICIT_PATH_INFO = "explicitPathInfo";
    private static final String MISSING_MEMBER_MESSAGE = " member is required in pce-path";
    public static final String JSON_NOT_NULL = "JsonNode can not be null";
    public static final byte SOURCE_DEVICEID_INDEX = 0;
    public static final byte SOURCE_PORTNO_INDEX = 1;
    public static final byte DESTINATION_DEVICEID_INDEX = 2;
    public static final byte DESTINATION_PORTNO_INDEX = 3;

    @Override
    public PcePath decode(ObjectNode json, CodecContext context) {
        if (json == null || !json.isObject()) {
            log.error("Empty json input");
            return null;
        }

        // build pce-path
        PcePath.Builder resultBuilder = new DefaultPcePath.Builder();

        // retrieve source
        JsonNode jNode = json.get(SOURCE);
        if (jNode != null) {
            String src = jNode.asText();
            resultBuilder.source(src);
        }

        // retrieve destination
        jNode = json.get(DESTINATION);
        if (jNode != null) {
            String dst = jNode.asText();
            resultBuilder.destination(dst);
        }

        // retrieve lsp-type
        jNode = json.get(LSP_TYPE);
        if (jNode != null) {
            String lspType = jNode.asText();
            //Validating LSP type
            int type = Integer.parseInt(lspType);
            if ((type < 0) || (type > 2)) {
                return null;
            }
            resultBuilder.lspType(lspType);
        }

        // retrieve symbolic-path-name
        jNode = json.get(SYMBOLIC_PATH_NAME);
        if (jNode != null) {
            String name = jNode.asText();
            resultBuilder.name(name);
        }

        // retrieve constraint
        JsonNode constraintJNode = (JsonNode) json.path(CONSTRAINT);
        if ((constraintJNode != null) && (!constraintJNode.isMissingNode())) {
            // retrieve cost
            jNode = constraintJNode.get(COST);
            if (jNode != null) {
                String cost = jNode.asText();
                //Validating Cost type
                int costType = Integer.parseInt(cost);
                if ((costType < 1) || (costType > 2)) {
                    return null;
                }
                resultBuilder.costConstraint(cost);
            }

            // retrieve bandwidth
            jNode = constraintJNode.get(BANDWIDTH);
            if (jNode != null) {
                String bandwidth = jNode.asText();
                double bw = Double.parseDouble(bandwidth);
                if (bw < 0) {
                    return null;
                }
                resultBuilder.bandwidthConstraint(bandwidth);
            }
        }

        // Retrieve explicit path info
        JsonNode explicitPathInfo = json.get(EXPLICIT_PATH_INFO);
        if (explicitPathInfo != null) {
            List<ExplicitPathInfo> explicitPathInfoList =
                    ImmutableList.copyOf(jsonNodeToExplicitPathInfo(explicitPathInfo));
            if (explicitPathInfoList != null) {
                resultBuilder.explicitPathInfo(explicitPathInfoList);
            }
        }

        return resultBuilder.build();
    }

    private ExplicitPathInfo createListOfExplicitPathObj(JsonNode node) {
        int explicitPathType = Integer.parseInt(node.get("type").asText());
        DeviceId deviceId;
        PortNumber portNo;
        NetworkResource res;
        LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
        if ((explicitPathType < 0) || (explicitPathType > 1)) {
            return null;
        }
        ExplicitPathInfo.Type type = ExplicitPathInfo.Type.values()[explicitPathType];
        String subType = node.get("subtype").asText();
        if (Integer.parseInt(subType) == 0) {
            res = DeviceId.deviceId(node.get("value").asText());
        } else if (Integer.parseInt(subType) == 1) {

            String[] splitted = node.get("value").asText().split("/");

            if (splitted[SOURCE_DEVICEID_INDEX] != null
                    && splitted[SOURCE_PORTNO_INDEX] != null
                    && splitted[DESTINATION_DEVICEID_INDEX] != null
                    && splitted[DESTINATION_PORTNO_INDEX] != null) {
                return null;
            }
            deviceId = DeviceId.deviceId(splitted[SOURCE_DEVICEID_INDEX]);
            portNo = PortNumber.portNumber(splitted[SOURCE_PORTNO_INDEX]);
            ConnectPoint cpSrc = new ConnectPoint(deviceId, portNo);
            deviceId = DeviceId.deviceId(splitted[DESTINATION_DEVICEID_INDEX]);
            portNo = PortNumber.portNumber(splitted[DESTINATION_PORTNO_INDEX]);
            ConnectPoint cpDst = new ConnectPoint(deviceId, portNo);
            res = DefaultLink.builder()
                    .providerId(ProviderId.NONE)
                    .src(cpSrc)
                    .dst(cpDst)
                    .type(DIRECT)
                    .state(ACTIVE)
                    .build();
        } else {
            return null;
        }

        return new ExplicitPathInfo(type, res);
    }

    private Collection<ExplicitPathInfo> jsonNodeToExplicitPathInfo(JsonNode explicitPathInfo) {
        checkNotNull(explicitPathInfo, JSON_NOT_NULL);

        Integer i = 0;
        NetworkResource res;
        LinkedList<ExplicitPathInfo> list = Lists.newLinkedList();
        if (explicitPathInfo.isArray()) {
            for (JsonNode node : explicitPathInfo) {
                ExplicitPathInfo obj = createListOfExplicitPathObj(node);
                if (obj == null) {
                    return null;
                }
                list.add(obj);
            }
        } else {
            ExplicitPathInfo obj = createListOfExplicitPathObj(explicitPathInfo);
            if (obj == null) {
                return null;
            }
            list.add(obj);
        }

        return Collections.unmodifiableCollection(list);
    }

    @Override
    public ObjectNode encode(PcePath path, CodecContext context) {
        checkNotNull(path, "path output cannot be null");
        ObjectNode result = context.mapper()
                .createObjectNode()
                .put(PATH_ID, path.id().id())
                .put(SOURCE, path.source())
                .put(DESTINATION, path.destination())
                .put(LSP_TYPE, path.lspType().type())
                .put(SYMBOLIC_PATH_NAME, path.name());

        ObjectNode constraintNode = context.mapper()
                .createObjectNode()
                .put(COST, ((CostConstraint) path.costConstraint()).type().type())
                .put(BANDWIDTH, ((PceBandwidthConstraint) path.bandwidthConstraint()).bandwidth().bps());

        if (path.explicitPathInfo() != null && !path.explicitPathInfo().isEmpty()) {
            ArrayNode arrayNode = context.mapper().createArrayNode();
            for (ExplicitPathInfo e : path.explicitPathInfo()) {
                ObjectNode node = context.mapper()
                        .createObjectNode()
                        .put("type", e.type().toString())
                        .put("value", e.value().toString());
                arrayNode.add(node);
            }
            result.set(EXPLICIT_PATH_INFO, arrayNode);
        }

        result.set(CONSTRAINT, constraintNode);
        return result;
    }
}
