// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"math"
	"os"
	"sort"
	"strings"

	humanize "github.com/dustin/go-humanize"
)

type EventArgs struct {
	Count uint64
	Value uint64
}

type Event struct {
	Args EventArgs
	Cat  string
	Id   string
	Name string
	Ph   string
	Tid  uint
	Ts   float64
}

type TraceJson struct {
	TraceEvents []Event
}

// This is used to compute the lapsed time of the count: We're given two
// records: one at start-time and one at stop-time.
type EventKey struct {
	Cat string
	Id  string
	Ph  string
	Tid uint
}

func makeEventKey(event Event) EventKey {
	return EventKey{event.Cat,
		event.Id,
		event.Ph,
		event.Tid}
}

type RecordType int
const (
	CountRecordType RecordType = iota
	ValueRecordType
)

type CpuRecord struct {
	Name     string
	Id       string
	Type     RecordType
	Value    uint64
	// Duration over which the count applies or zero for non-counter
	// events.
	Duration float64
}

// This is for sorting CpuRecord by ids.
type CpuRecordArray []CpuRecord

func (a CpuRecordArray) Len() int           { return len(a) }
func (a CpuRecordArray) Swap(i, j int)      { a[i], a[j] = a[j], a[i] }
func (a CpuRecordArray) Less(i, j int) bool { return a[i].Id < a[j].Id }

func commaFormat(n uint64) string {
	// humanize takes int64s. If we get a number that big don't print
	// garbage, just don't comma-ize it.
	if n > math.MaxInt64 {
		return fmt.Sprintf("%d", n)
	}
	return humanize.Comma(int64(n))
}

var (
	outputFile string
	title      string
)

func init() {
	flag.StringVar(&outputFile, "output", "", "Where to write the result to")
	flag.StringVar(&title, "title", "Table of events", "The title of the report")
}

func main() {
	log.SetFlags(0)
	log.SetPrefix("tally: ")
	log.Print("started")

	flag.Parse()

	if flag.NArg() > 1 {
		log.Fatal("Too many arguments")
	}

	inputFile := flag.Arg(0)

	var in io.Reader
	var out io.Writer
	if inputFile != "" {
		f, err := os.Open(inputFile)
		if err != nil {
			log.Fatalln("Unable to open input file:", err)
		}
		in = io.Reader(f)
		defer f.Close()
	} else {
		in = os.Stdin
	}
	if outputFile != "" {
		f, err := os.Create(outputFile)
		if err != nil {
			log.Fatalln("Unable to open output file:", err)
		}
		out = io.Writer(f)
		defer f.Close()
	} else {
		out = os.Stdout
	}

	decoder := json.NewDecoder(in)
	var json TraceJson
	if err := decoder.Decode(&json); err != nil {
		log.Fatalln("Error reading json input:", err)
		return
	}

	fmt.Fprintf(out, "%s\n", title)

	startEvents := make(map[EventKey]Event)
	endEvents := make(map[EventKey]Event)
	perCpuRecords := make(map[uint]CpuRecordArray)

	// First pass: Collect data for each cpu.

	for _, event := range json.TraceEvents {
		if !strings.HasPrefix(event.Cat, "cpu:") {
			continue
		}
		if (event.Ph != "C") {
			continue;
		}
		key := makeEventKey(event)
		start, start_ok := startEvents[key]
		if !start_ok {
			startEvents[key] = event
			continue
		}
		// TODO(dje): For now we assume there are only two records
		// for each event: start and end. Instead accumulate the
		// results for counter events.
		_, end_ok := endEvents[key]
		if end_ok {
			log.Println("WARNING: unexpected extra record")
			continue
		}
		endEvents[key] = event
		cpu := event.Tid
		// Assume we have a value, unless Count is non-zero.
		// If they're both zero we don't want to print the value
		// as a rate.
		countOrValue := event.Args.Value
		recordType := ValueRecordType
		if (event.Args.Count != 0) {
			recordType = CountRecordType
			countOrValue = event.Args.Count
		}
		if recordType == CountRecordType {
			countOrValue = countOrValue - start.Args.Count
		}
		perCpuRecords[cpu] = append(perCpuRecords[cpu], CpuRecord{
			event.Name,
			event.Id,
			recordType,
			countOrValue,
			event.Ts - start.Ts})
	}

	// Value records are only emitted once, for the end value.
	// We don't process value records in the above loop because if the
	// value is zero we can't tell if the record is the initial count
	// record.
	for key, event := range startEvents {
		_, end_ok := endEvents[key]
		if !end_ok {
			// A non-zero count field for the first record
			// is an error.
			if event.Args.Count != 0 {
				continue
			}
			cpu := event.Tid
			perCpuRecords[cpu] = append(perCpuRecords[cpu], CpuRecord{
				event.Name,
				event.Id,
				ValueRecordType,
				event.Args.Value,
				event.Ts})
		}
	}

	// Second pass: Print

	var cpus []uint
	for k := range perCpuRecords {
		cpus = append(cpus, k)
	}
	sort.Slice(cpus, func(i, j int) bool { return cpus[i] < cpus[j] })
	for _, cpu := range cpus {
		if cpu == 0 {
			fmt.Fprintf(out, "System-wide\n")
		} else {
			fmt.Fprintf(out, "Cpu %d\n", cpu-1)
		}
		records := perCpuRecords[cpu]
		sort.Sort(records)
		for _, record := range records {
			value_string := fmt.Sprintf("%16s", commaFormat(record.Value))
			if record.Type == CountRecordType && record.Duration != 0 {
				microsecsPerSec := uint64(1000 * 1000)
				value_string += fmt.Sprintf(
					" (%s/sec)",
					commaFormat((record.Value*microsecsPerSec)/uint64(record.Duration)))
			}
			fmt.Fprintf(out, "  %-38s %s\n",
				value_string, record.Name)
		}
	}

	log.Print("done")
	os.Exit(0)
}
