/*
 * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.jfr.internal.tool;

import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Path;
import java.time.Instant;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;

import jdk.jfr.EventType;
import jdk.jfr.internal.MetadataDescriptor;
import jdk.jfr.internal.Type;
import jdk.jfr.internal.consumer.ChunkHeader;
import jdk.jfr.internal.consumer.RecordingInput;

final class Summary extends Command {
    private final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withLocale(Locale.UK).withZone(ZoneOffset.UTC);

    @Override
    public String getName() {
        return "summary";
    }

    private static class Statistics {
        Statistics(String name) {
            this.name = name;
        }
        String name;
        long count;
        long size;
    }

    @Override
    public List<String> getOptionSyntax() {
        return Collections.singletonList("<file>");
    }

    @Override
    public void displayOptionUsage(PrintStream stream) {
        stream.println("  <file>   Location of the recording file (.jfr) to display information about");
    }

    @Override
    public String getDescription() {
        return "Display general information about a recording file (.jfr)";
    }

    @Override
    public void execute(Deque<String> options) throws UserSyntaxException, UserDataException {
        ensureMaxArgumentCount(options, 1);
        Path p = getJFRInputFile(options);
        try {
            printInformation(p);
        } catch (IOException e) {
            couldNotReadError(p, e);
        }
    }

    private void printInformation(Path p) throws IOException {
        long totalDuration = 0;
        long chunks = 0;

        try (RecordingInput input = new RecordingInput(p.toFile())) {
            ChunkHeader first = new ChunkHeader(input);
            ChunkHeader ch = first;
            String eventPrefix = Type.EVENT_NAME_PREFIX;
            if (first.getMajor() == 1) {
                eventPrefix = "com.oracle.jdk.";
            }
            HashMap<Long, Statistics> stats = new HashMap<>();
            stats.put(0L, new Statistics(eventPrefix + "Metadata"));
            stats.put(1L, new Statistics(eventPrefix + "CheckPoint"));
            int minWidth = 0;
            while (true) {
                long chunkEnd = ch.getEnd();
                MetadataDescriptor md = ch.readMetadata();

                for (EventType eventType : md.getEventTypes()) {
                    stats.computeIfAbsent(eventType.getId(), (e) -> new Statistics(eventType.getName()));
                    minWidth = Math.max(minWidth, eventType.getName().length());
                }

                totalDuration += ch.getDurationNanos();
                chunks++;
                input.position(ch.getEventStart());
                while (input.position() < chunkEnd) {
                    long pos = input.position();
                    int size = input.readInt();
                    long eventTypeId = input.readLong();
                    Statistics s = stats.get(eventTypeId);
                    if (s != null) {
                        s.count++;
                        s.size += size;
                    }
                    input.position(pos + size);
                }
                if (ch.isLastChunk()) {
                    break;
                }
                ch = ch.nextHeader();
            }
            println();
            long epochSeconds = first.getStartNanos() / 1_000_000_000L;
            long adjustNanos = first.getStartNanos() - epochSeconds * 1_000_000_000L;
            println(" Version: " + first.getMajor() + "." + first.getMinor());
            println(" Chunks: " + chunks);
            println(" Start: " + DATE_FORMAT.format(Instant.ofEpochSecond(epochSeconds, adjustNanos)) + " (UTC)");
            println(" Duration: " + (totalDuration + 500_000_000) / 1_000_000_000 + " s");

            List<Statistics> statsList = new ArrayList<>(stats.values());
            Collections.sort(statsList, (u, v) -> Long.compare(v.count, u.count));
            println();
            String header = "      Count  Size (bytes) ";
            String typeHeader = " Event Type";
            minWidth = Math.max(minWidth, typeHeader.length());
            println(typeHeader + pad(minWidth - typeHeader.length(), ' ') + header);
            println(pad(minWidth + header.length(), '='));
            for (Statistics s : statsList) {
                System.out.printf(" %-" + minWidth + "s%10d  %12d\n", s.name, s.count, s.size);
            }
        }
    }

    private String pad(int count, char c) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(c);
        }
        return sb.toString();
    }
}
