// Copyright 2016 The Go 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 benchfmt provides readers and writers for the Go benchmark format.
//
// The format is documented at https://golang.org/design/14313-benchmark-format
package benchfmt

import (
	"bufio"
	"fmt"
	"io"
	"sort"
	"strconv"
	"strings"
	"unicode"
)

// Reader reads benchmark results from an io.Reader.
type Reader struct {
	s       *bufio.Scanner
	labels  Labels
	lineNum int
}

// TODO(quentin): Make Reader have a Scanner-style interface instead, to match db.Query.

// NewReader creates a BenchmarkReader that reads from r.
func NewReader(r io.Reader) *Reader {
	return &Reader{
		s:      bufio.NewScanner(r),
		labels: make(Labels),
	}
}

// AddLabels adds additional labels as if they had been read from the file.
// It must be called before the first call to r.Next.
func (r *Reader) AddLabels(labels Labels) {
	for k, v := range labels {
		r.labels[k] = v
	}
}

// Result represents a single line from a benchmark file.
// All information about that line is self-contained in the Result.
type Result struct {
	// Labels is the set of persistent labels that apply to the result.
	// Labels must not be modified.
	Labels Labels
	// NameLabels is the set of ephemeral labels that were parsed
	// from the benchmark name/line.
	// NameLabels must not be modified.
	NameLabels Labels
	// LineNum is the line number on which the result was found
	LineNum int
	// Content is the verbatim input line of the benchmark file, beginning with the string "Benchmark".
	Content string
}

// Labels is a set of key-value strings.
type Labels map[string]string

// TODO(quentin): Add String and Equal methods to Labels?

// Keys returns a sorted list of the keys in l.
func (l Labels) Keys() []string {
	var out []string
	for k := range l {
		out = append(out, k)
	}
	sort.Strings(out)
	return out
}

// A Printer prints a sequence of benchmark results.
type Printer struct {
	w      io.Writer
	labels Labels
}

// NewPrinter constructs a BenchmarkPrinter writing to w.
func NewPrinter(w io.Writer) *Printer {
	return &Printer{w: w}
}

// Print writes the lines necessary to recreate r.
func (p *Printer) Print(r *Result) error {
	var keys []string
	// Print removed keys first.
	for k := range p.labels {
		if r.Labels[k] == "" {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)
	for _, k := range keys {
		if _, err := fmt.Fprintf(p.w, "%s:\n", k); err != nil {
			return err
		}
	}
	// Then print new or changed keys.
	keys = keys[:0]
	for k, v := range r.Labels {
		if v != "" && p.labels[k] != v {
			keys = append(keys, k)
		}
	}
	sort.Strings(keys)
	for _, k := range keys {
		if _, err := fmt.Fprintf(p.w, "%s: %s\n", k, r.Labels[k]); err != nil {
			return err
		}
	}
	// Finally print the actual line itself.
	if _, err := fmt.Fprintf(p.w, "%s\n", r.Content); err != nil {
		return err
	}
	p.labels = r.Labels
	return nil
}

// parseNameLabels extracts extra labels from a benchmark name and sets them in labels.
func parseNameLabels(name string, labels Labels) {
	dash := strings.LastIndex(name, "-")
	if dash >= 0 {
		// Accept -N as an alias for /gomaxprocs=N
		_, err := strconv.Atoi(name[dash+1:])
		if err == nil {
			labels["gomaxprocs"] = name[dash+1:]
			name = name[:dash]
		}
	}
	parts := strings.Split(name, "/")
	labels["name"] = parts[0]
	for i, sub := range parts[1:] {
		equals := strings.Index(sub, "=")
		var key string
		if equals >= 0 {
			key, sub = sub[:equals], sub[equals+1:]
		} else {
			key = fmt.Sprintf("sub%d", i+1)
		}
		labels[key] = sub
	}
}

// newResult parses a line and returns a Result object for the line.
func newResult(labels Labels, lineNum int, name, content string) *Result {
	r := &Result{
		Labels:     labels,
		NameLabels: make(Labels),
		LineNum:    lineNum,
		Content:    content,
	}
	parseNameLabels(name, r.NameLabels)
	return r
}

// copy returns a new copy of the labels map, to protect against
// future modifications to labels.
func (l Labels) copy() Labels {
	new := make(Labels)
	for k, v := range l {
		new[k] = v
	}
	return new
}

// TODO(quentin): How to represent and efficiently group multiple lines?

// Next returns the next benchmark result from the file. If there are
// no further results, it returns nil, io.EOF.
func (r *Reader) Next() (*Result, error) {
	copied := false
	for r.s.Scan() {
		r.lineNum++
		line := r.s.Text()
		if key, value, ok := parseKeyValueLine(line); ok {
			if !copied {
				copied = true
				r.labels = r.labels.copy()
			}
			// TODO(quentin): Spec says empty value is valid, but
			// we need a way to cancel previous labels, so we'll
			// treat an empty value as a removal.
			if value == "" {
				delete(r.labels, key)
			} else {
				r.labels[key] = value
			}
			continue
		}
		if fullName, ok := parseBenchmarkLine(line); ok {
			return newResult(r.labels, r.lineNum, fullName, line), nil
		}
	}
	if err := r.s.Err(); err != nil {
		return nil, err
	}
	return nil, io.EOF
}

// parseKeyValueLine attempts to parse line as a key: value pair. ok
// indicates whether the line could be parsed.
func parseKeyValueLine(line string) (key, val string, ok bool) {
	for i, c := range line {
		if i == 0 && !unicode.IsLower(c) {
			return
		}
		if unicode.IsSpace(c) || unicode.IsUpper(c) {
			return
		}
		if i > 0 && c == ':' {
			key = line[:i]
			val = line[i+1:]
			break
		}
	}
	if val == "" {
		ok = true
		return
	}
	for len(val) > 0 && (val[0] == ' ' || val[0] == '\t') {
		val = val[1:]
		ok = true
	}
	return
}

// parseBenchmarkLine attempts to parse line as a benchmark result. If
// successful, fullName is the name of the benchmark with the
// "Benchmark" prefix stripped, and ok is true.
func parseBenchmarkLine(line string) (fullName string, ok bool) {
	space := strings.IndexFunc(line, unicode.IsSpace)
	if space < 0 {
		return
	}
	name := line[:space]
	if !strings.HasPrefix(name, "Benchmark") {
		return
	}
	return name[len("Benchmark"):], true
}
