/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.apache.cassandra.tools.nodetool.stats;

import java.io.PrintStream;
import java.util.List;

public class TableStatsPrinter
{
    public static StatsPrinter from(String format)
    {
        switch (format)
        {
            case "json":
                return new StatsPrinter.JsonPrinter();
            case "yaml":
                return new StatsPrinter.YamlPrinter();
            default:
                return new DefaultPrinter();
        }
    }

    private static class DefaultPrinter implements StatsPrinter<TableStatsHolder>
    {
        @Override
        public void print(TableStatsHolder data, PrintStream out)
        {
            out.println("Total number of tables: " + data.numberOfTables);
            out.println("----------------");

            List<StatsKeyspace> keyspaces = data.keyspaces;
            for (StatsKeyspace keyspace : keyspaces)
            {
                // print each keyspace's information
                out.println("Keyspace : " + keyspace.name);
                out.println("\tRead Count: " + keyspace.readCount);
                out.println("\tRead Latency: " + keyspace.readLatency() + " ms");
                out.println("\tWrite Count: " + keyspace.writeCount);
                out.println("\tWrite Latency: " + keyspace.writeLatency() + " ms");
                out.println("\tPending Flushes: " + keyspace.pendingFlushes);

                // print each table's information
                List<StatsTable> tables = keyspace.tables;
                for (StatsTable table : tables)
                {
                    out.println("\t\tTable" + (table.isIndex ? " (index): " : ": ") + table.name);
                    out.println("\t\tSSTable count: " + table.sstableCount);
                    if (table.isLeveledSstable)
                        out.println("\t\tSSTables in each level: [" + String.join(", ",
                                                                                  table.sstablesInEachLevel) + "]");

                    out.println("\t\tSpace used (live): " + table.spaceUsedLive);
                    out.println("\t\tSpace used (total): " + table.spaceUsedTotal);
                    out.println("\t\tSpace used by snapshots (total): " + table.spaceUsedBySnapshotsTotal);

                    if (table.offHeapUsed)
                        out.println("\t\tOff heap memory used (total): " + table.offHeapMemoryUsedTotal);
                    out.println("\t\tSSTable Compression Ratio: " + table.sstableCompressionRatio);
                    out.println("\t\tNumber of partitions (estimate): " + table.numberOfPartitionsEstimate);
                    out.println("\t\tMemtable cell count: " + table.memtableCellCount);
                    out.println("\t\tMemtable data size: " + table.memtableDataSize);

                    if (table.memtableOffHeapUsed)
                        out.println("\t\tMemtable off heap memory used: " + table.memtableOffHeapMemoryUsed);
                    out.println("\t\tMemtable switch count: " + table.memtableSwitchCount);
                    out.println("\t\tLocal read count: " + table.localReadCount);
                    out.printf("\t\tLocal read latency: %01.3f ms%n", table.localReadLatencyMs);
                    out.println("\t\tLocal write count: " + table.localWriteCount);
                    out.printf("\t\tLocal write latency: %01.3f ms%n", table.localWriteLatencyMs);
                    out.println("\t\tPending flushes: " + table.pendingFlushes);
                    out.println("\t\tPercent repaired: " + table.percentRepaired);

                    out.println("\t\tBloom filter false positives: " + table.bloomFilterFalsePositives);
                    out.printf("\t\tBloom filter false ratio: %01.5f%n", table.bloomFilterFalseRatio);
                    out.println("\t\tBloom filter space used: " + table.bloomFilterSpaceUsed);

                    if (table.bloomFilterOffHeapUsed)
                        out.println("\t\tBloom filter off heap memory used: " + table.bloomFilterOffHeapMemoryUsed);
                    if (table.indexSummaryOffHeapUsed)
                        out.println("\t\tIndex summary off heap memory used: " + table.indexSummaryOffHeapMemoryUsed);
                    if (table.compressionMetadataOffHeapUsed)
                        out.println("\t\tCompression metadata off heap memory used: " + table.compressionMetadataOffHeapMemoryUsed);

                    out.println("\t\tCompacted partition minimum bytes: " + table.compactedPartitionMinimumBytes);
                    out.println("\t\tCompacted partition maximum bytes: " + table.compactedPartitionMaximumBytes);
                    out.println("\t\tCompacted partition mean bytes: " + table.compactedPartitionMeanBytes);
                    out.println("\t\tAverage live cells per slice (last five minutes): " + table.averageLiveCellsPerSliceLastFiveMinutes);
                    out.println("\t\tMaximum live cells per slice (last five minutes): " + table.maximumLiveCellsPerSliceLastFiveMinutes);
                    out.println("\t\tAverage tombstones per slice (last five minutes): " + table.averageTombstonesPerSliceLastFiveMinutes);
                    out.println("\t\tMaximum tombstones per slice (last five minutes): " + table.maximumTombstonesPerSliceLastFiveMinutes);
                    out.println("\t\tDropped Mutations: " + table.droppedMutations);
                    out.println("");
                }
                out.println("----------------");
            }
        }
    }
}