/*
 * Copyright 2015-present Open Networking Laboratory
 *
 * 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.cli.net;

import java.util.List;

import org.apache.karaf.shell.commands.Command;
import org.apache.karaf.shell.commands.Option;
import org.onosproject.cli.AbstractShellCommand;
import org.onosproject.cluster.ClusterService;
import org.onosproject.cluster.ControllerNode;
import org.onosproject.cluster.NodeId;
import org.onosproject.store.primitives.PartitionAdminService;
import org.onosproject.store.service.PartitionClientInfo;
import org.onosproject.store.service.PartitionInfo;
import org.onosproject.store.service.StorageAdminService;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Ordering;

/**
 * Command to list the database partitions in the system.
 */
@Command(scope = "onos", name = "partitions",
        description = "Lists information about partitions in the system")
public class PartitionsListCommand extends AbstractShellCommand {

    @Option(name = "-c", aliases = "--clients",
            description = "Show inforamtion about partition clients",
            required = false, multiValued = false)
    private boolean reportClientInfo = false;

    private static final String SERVER_FMT = "%-20s %8s %25s %s";
    private static final String CLIENT_FMT = "%-20s %8s %10s %25s";

    /**
     * Displays partition info as text.
     *
     * @param partitionInfo partition descriptions
     */
    private void displayPartitions(List<PartitionInfo> partitionInfo) {
        if (partitionInfo.isEmpty()) {
            return;
        }
        print("----------------------------------------------------------");
        print(SERVER_FMT, "Name", "Term", "Members", "");
        print("----------------------------------------------------------");

        for (PartitionInfo info : partitionInfo) {
            boolean first = true;
            for (String member : Ordering.natural().sortedCopy(info.members())) {
                if (first) {
                    print(SERVER_FMT, info.name(), info.term(), member,
                            member.equals(info.leader()) ? "*" : "");
                    first = false;
                } else {
                    print(SERVER_FMT, "", "", member,
                            member.equals(info.leader()) ? "*" : "");
                }
            }
            if (!first) {
                print("----------------------------------------------------------");
            }
        }
    }

    /**
     * Displays partition client info as text.
     *
     * @param partitionClientInfo partition client information
     */
    private void displayPartitionClients(List<PartitionClientInfo> partitionClientInfo) {
        if (partitionClientInfo.isEmpty()) {
            return;
        }
        ClusterService clusterService = get(ClusterService.class);
        print("-------------------------------------------------------------------");
        print(CLIENT_FMT, "Name", "SessionId", "Status", "Servers");
        print("-------------------------------------------------------------------");

        for (PartitionClientInfo info : partitionClientInfo) {
            boolean first = true;
            for (NodeId serverId : Ordering.natural().sortedCopy(info.servers())) {
                ControllerNode server = clusterService.getNode(serverId);
                String serverString = String.format("%s:%d", server.id(), server.tcpPort());
                if (first) {
                    print(CLIENT_FMT, info.partitionId(), info.sessionId(),
                            info.status(), serverString);
                    first = false;
                } else {
                    print(CLIENT_FMT, "", "", "", serverString);
                }
            }
            if (!first) {
                print("-------------------------------------------------------------------");
            }
        }
    }

    /**
     * Converts partition info into a JSON object.
     *
     * @param partitionInfo partition descriptions
     */
    private JsonNode json(List<PartitionInfo> partitionInfo) {
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode partitions = mapper.createArrayNode();

        // Create a JSON node for each partition
        partitionInfo.stream()
            .forEach(info -> {
                ObjectNode partition = mapper.createObjectNode();

                // Add each member to the "members" array for this partition
                ArrayNode members = partition.putArray("members");
                info.members()
                        .stream()
                        .forEach(members::add);

                // Complete the partition attributes and add it to the array
                partition.put("name", info.name())
                         .put("term", info.term())
                         .put("leader", info.leader());
                partitions.add(partition);

            });

        return partitions;
    }

    /**
     * Converts partition client info into a JSON object.
     *
     * @param partitionClientInfo partition client descriptions
     */
    private JsonNode jsonForClientInfo(List<PartitionClientInfo> partitionClientInfo) {
        ObjectMapper mapper = new ObjectMapper();
        ArrayNode partitions = mapper.createArrayNode();
        ClusterService clusterService = get(ClusterService.class);

        // Create a JSON node for each partition client
        partitionClientInfo.stream()
            .forEach(info -> {
                ObjectNode partition = mapper.createObjectNode();

                // Add each member to the "servers" array for this partition
                ArrayNode servers = partition.putArray("servers");
                info.servers()
                        .stream()
                        .map(clusterService::getNode)
                        .map(node -> String.format("%s:%d", node.ip(), node.tcpPort()))
                        .forEach(servers::add);

                // Complete the partition attributes and add it to the array
                partition.put("partitionId", info.partitionId().toString())
                         .put("sessionId", info.sessionId())
                         .put("status", info.status().toString());
                partitions.add(partition);

            });

        return partitions;
    }

    @Override
    protected void execute() {
        StorageAdminService storageAdminService = get(StorageAdminService.class);
        if (reportClientInfo) {
            PartitionAdminService partitionAdminService = get(PartitionAdminService.class);
            List<PartitionClientInfo> partitionClientInfo = partitionAdminService.partitionClientInfo();
            if (outputJson()) {
                print("%s", jsonForClientInfo(partitionClientInfo));
            } else {
                displayPartitionClients(partitionClientInfo);
            }
        } else {
            List<PartitionInfo> partitionInfo = storageAdminService.getPartitionInfo();
            if (outputJson()) {
                print("%s", json(partitionInfo));
            } else {
                displayPartitions(partitionInfo);
            }
        }
    }
}
