/*
 * Copyright 2021-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.kubevirtnetworking.codec;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.ImmutableMap;
import org.onlab.packet.IpAddress;
import org.onlab.packet.MacAddress;
import org.onosproject.codec.CodecContext;
import org.onosproject.codec.JsonCodec;
import org.onosproject.kubevirtnetworking.api.DefaultKubevirtRouter;
import org.onosproject.kubevirtnetworking.api.KubevirtPeerRouter;
import org.onosproject.kubevirtnetworking.api.KubevirtRouter;
import org.slf4j.Logger;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Kubevirt router codec used for serializing and de-serializing JSON string.
 */
public final class KubevirtRouterCodec extends JsonCodec<KubevirtRouter> {

    private final Logger log = getLogger(getClass());

    private static final String NAME = "name";
    private static final String DESCRIPTION = "description";
    private static final String ENABLE_SNAT = "enableSnat";
    private static final String INTERNAL = "internal";
    private static final String EXTERNAL = "external";
    private static final String PEER_ROUTER = "peerRouter";
    private static final String IP_ADDRESS = "ip";
    private static final String MAC_ADDRESS = "mac";
    private static final String NETWORK = "network";

    private static final String MISSING_MESSAGE = " is required in KubevirtRouter";

    @Override
    public ObjectNode encode(KubevirtRouter router, CodecContext context) {
        checkNotNull(router, "Kubevirt router pool cannot be null");

        ObjectNode result = context.mapper().createObjectNode()
                .put(NAME, router.name())
                .put(ENABLE_SNAT, router.enableSnat());

        if (router.description() != null) {
            result.put(DESCRIPTION, router.description());
        }

        if (router.internal() != null && !router.internal().isEmpty()) {
            ArrayNode internal = context.mapper().createArrayNode();
            router.internal().forEach(internal::add);

            result.set(INTERNAL, internal);
        }

        if (router.external() != null && !router.external().isEmpty()) {
            ArrayNode external = context.mapper().createArrayNode();
            router.external().forEach((k, v) -> {
                ObjectNode item = context.mapper().createObjectNode();
                item.put(IP_ADDRESS, k);
                item.put(NETWORK, v);
                external.add(item);
            });
            result.set(EXTERNAL, external);
        }

        if (router.peerRouter() != null) {
            ObjectNode peerRouter = context.mapper().createObjectNode();
            peerRouter.put(IP_ADDRESS, router.peerRouter().ipAddress().toString());

            if (router.peerRouter().macAddress() != null) {
                peerRouter.put(MAC_ADDRESS, router.peerRouter().macAddress().toString());
            }

            result.set(PEER_ROUTER, peerRouter);
        }

        return result;
    }

    @Override
    public KubevirtRouter decode(ObjectNode json, CodecContext context) {
        if (json == null || !json.isObject()) {
            return null;
        }

        String name = nullIsIllegal(json.get(NAME).asText(),
                NAME + MISSING_MESSAGE);

        KubevirtRouter.Builder builder = DefaultKubevirtRouter.builder()
                .name(name);

        JsonNode descriptionJson = json.get(DESCRIPTION);
        if (descriptionJson != null) {
            builder.description(descriptionJson.asText());
        }

        JsonNode enableSnatJson = json.get(ENABLE_SNAT);
        if (enableSnatJson != null) {
            builder.enableSnat(enableSnatJson.asBoolean());
        }

        ArrayNode internalJson = (ArrayNode) json.get(INTERNAL);
        Set<String> internal = new HashSet<>();
        if (internalJson != null) {
            for (int i = 0; i < internalJson.size(); i++) {
                internal.add(internalJson.get(i).asText());
            }
            builder.internal(internal);
        }

        ObjectNode externalJson = (ObjectNode) json.get(EXTERNAL);
        if (externalJson != null) {
            Map<String, String> external = ImmutableMap.of(
                    externalJson.get(IP_ADDRESS).asText(),
                    externalJson.get(NETWORK).asText());
            builder.external(external);
        }

        ObjectNode peerRouterJson = (ObjectNode) json.get(PEER_ROUTER);
        if (peerRouterJson != null) {
            JsonNode ipJson = peerRouterJson.get(IP_ADDRESS);
            JsonNode macJson = peerRouterJson.get(MAC_ADDRESS);

            if (ipJson != null && macJson != null) {
                IpAddress ip = IpAddress.valueOf(ipJson.asText());
                MacAddress mac = MacAddress.valueOf(macJson.asText());
                KubevirtPeerRouter peer = new KubevirtPeerRouter(ip, mac);
                builder.peerRouter(peer);
            }

            // if mac address is not specified, we will not add mac address to peer router
            if (ipJson != null && macJson == null) {
                IpAddress ip = IpAddress.valueOf(ipJson.asText());
                KubevirtPeerRouter peer = new KubevirtPeerRouter(ip, null);
                builder.peerRouter(peer);
            }
        }

        return builder.build();
    }
}
