/*
 * 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.ignite.internal.performancestatistics;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Iterator;
import java.util.Set;
import java.util.stream.Collectors;
import org.apache.ignite.internal.performancestatistics.handlers.PrintHandler;
import org.apache.ignite.internal.processors.performancestatistics.FilePerformanceStatisticsReader;
import org.apache.ignite.internal.processors.performancestatistics.OperationType;
import org.apache.ignite.internal.util.typedef.internal.A;
import org.apache.ignite.internal.util.typedef.internal.CU;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.jetbrains.annotations.Nullable;

import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.joining;

/**
 * Performance statistics printer.
 */
public class PerformanceStatisticsPrinter {
    /**
     * @param args Program arguments or '-h' to get usage help.
     */
    public static void main(String... args) throws Exception {
        Parameters params = parseArguments(args);

        validateParameters(params);

        PrintStream ps = printStream(params.outFile);

        try {
            new FilePerformanceStatisticsReader(
                new PrintHandler(ps, params.ops, params.from, params.to,params.cacheIds))
                .read(singletonList(new File(params.statFileOrDir)));
        }
        finally {
            if (params.outFile != null)
                ps.close();
        }
    }

    /**
     * Parses arguments or print help.
     *
     * @param args Arguments to parse.
     * @return Program arguments.
     */
    private static Parameters parseArguments(String[] args) {
        if (args == null || args.length == 0 || "--help".equalsIgnoreCase(args[0]) || "-h".equalsIgnoreCase(args[0]))
            printHelp();

        Parameters params = new Parameters();

        Iterator<String> iter = Arrays.asList(args).iterator();

        params.statFileOrDir = iter.next();

        while (iter.hasNext()) {
            String arg = iter.next();

            if ("--out".equalsIgnoreCase(arg)) {
                A.ensure(iter.hasNext(), "Expected output file name");

                params.outFile = iter.next();
            }
            else if ("--ops".equalsIgnoreCase(arg)) {
                A.ensure(iter.hasNext(), "Expected operation types");

                String[] ops = iter.next().split(",");

                A.ensure(ops.length > 0, "Expected at least one operation");

                params.ops = new BitSet();

                for (String op : ops) {
                    OperationType opType = enumIgnoreCase(op, OperationType.class);

                    A.ensure(opType != null, "Unknown operation type [op=" + op + ']');

                    params.ops.set(opType.id());
                }
            }
            else if ("--from".equalsIgnoreCase(arg)) {
                A.ensure(iter.hasNext(), "Expected time from");

                params.from = Long.parseLong(iter.next());
            }
            else if ("--to".equalsIgnoreCase(arg)) {
                A.ensure(iter.hasNext(), "Expected time to");

                params.to = Long.parseLong(iter.next());
            }
            else if ("--caches".equalsIgnoreCase(arg)) {
                A.ensure(iter.hasNext(), "Expected cache names");

                String[] caches = iter.next().split(",");

                A.ensure(caches.length > 0, "Expected at least one cache name");

                params.cacheIds = Arrays.stream(caches).map(CU::cacheId).collect(Collectors.toSet());
            }
            else
                throw new IllegalArgumentException("Unknown command: " + arg);
        }

        return params;
    }

    /** Prints help. */
    private static void printHelp() {
        String ops = Arrays.stream(OperationType.values()).map(Enum::toString).collect(joining(", "));

        System.out.println("The script is used to print performance statistics files to the console or file." +
            U.nl() + U.nl() +
            "Usage: print-statistics.sh path_to_files [--out out_file] [--ops op_types] " +
            "[--from startTimeFrom] [--to startTimeTo] [--caches cache_names]" + U.nl() +
            U.nl() +
            "  path_to_files - Performance statistics file or files directory." + U.nl() +
            "  out_file      - Output file." + U.nl() +
            "  op_types      - Comma separated list of operation types to filter the output." + U.nl() +
            "  from          - The minimum operation start time to filter the output." + U.nl() +
            "  to            - The maximum operation start time to filter the output." + U.nl() +
            "  cache_names   - Comma separated list of cache names to filter the output." + U.nl() +
            U.nl() +
            "Times must be specified in the Unix time format in milliseconds." + U.nl() +
            "List of operation types: " + ops + '.');

        System.exit(0);
    }

    /** @param params Validates parameters. */
    private static void validateParameters(Parameters params) {
        File statFileOrDir = new File(params.statFileOrDir);

        A.ensure(statFileOrDir.exists(), "Performance statistics file or files directory does not exists");
    }

    /** @return Print stream to the console or file. */
    private static PrintStream printStream(@Nullable String outFile) {
        PrintStream ps;

        if (outFile != null) {
            try {
                ps = new PrintStream(new BufferedOutputStream(new FileOutputStream(new File(outFile), true)));
            }
            catch (IOException e) {
                throw new IllegalArgumentException("Cannot write to output file", e);
            }
        }
        else
            ps = System.out;

        return ps;
    }

    /**
     * Gets the enum for the given name ignore case.
     *
     * @param name Enum name.
     * @param cls Enum class.
     * @return The enum or {@code null} if not found.
     */
    private static <E extends Enum<E>> @Nullable E enumIgnoreCase(String name, Class<E> cls) {
        for (E e : cls.getEnumConstants()) {
            if (e.name().equalsIgnoreCase(name))
                return e;
        }

        return null;
    }

    /** Printer parameters. */
    private static class Parameters {
        /** Performance statistics file or files directory. */
        private String statFileOrDir;

        /** Output file. */
        @Nullable private String outFile;

        /** Operation types to print. */
        @Nullable private BitSet ops;

        /** The minimum operation start time to filter the output. */
        private long from = Long.MIN_VALUE;

        /** The maximum operation start time to filter the output. */
        private long to = Long.MAX_VALUE;

        /** Cache identifiers to filter the output. */
        @Nullable private Set<Integer> cacheIds;
    }
}
