// Copyright 2022 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

import (
	"bytes"
	"fmt"
	"io"
)

// A Writer writes the Go benchmark format.
type Writer struct {
	w   io.Writer
	buf bytes.Buffer

	first      bool
	fileConfig map[string]Config
	order      []string
}

// NewWriter returns a writer that writes Go benchmark results to w.
func NewWriter(w io.Writer) *Writer {
	return &Writer{w: w, first: true, fileConfig: make(map[string]Config)}
}

// Write writes Record rec to w. If rec is a *Result and rec's file
// configuration differs from the current file configuration in w, it
// first emits the appropriate file configuration lines. For
// Result.Values that have a non-zero OrigUnit, this uses OrigValue and
// OrigUnit in order to better reproduce the original input.
func (w *Writer) Write(rec Record) error {
	switch rec := rec.(type) {
	case *Result:
		return w.writeResult(rec)
	case *SyntaxError:
		// Ignore
		return nil
	}
	return fmt.Errorf("unknown Record type %T", rec)
}

func (w *Writer) writeResult(res *Result) error {
	// If any file config changed, write out the changes.
	if len(w.fileConfig) != len(res.Config) {
		w.writeFileConfig(res)
	} else {
		for _, cfg := range res.Config {
			if have, ok := w.fileConfig[cfg.Key]; !ok || !bytes.Equal(cfg.Value, have.Value) || cfg.File != have.File {
				w.writeFileConfig(res)
				break
			}
		}
	}

	// Print the benchmark line.
	fmt.Fprintf(&w.buf, "Benchmark%s %d", res.Name, res.Iters)
	for _, val := range res.Values {
		if val.OrigUnit == "" {
			fmt.Fprintf(&w.buf, " %v %s", val.Value, val.Unit)
		} else {
			fmt.Fprintf(&w.buf, " %v %s", val.OrigValue, val.OrigUnit)
		}
	}
	w.buf.WriteByte('\n')

	w.first = false

	// Flush the buffer out to the io.Writer. Write to the buffer
	// can't fail, so we only have to check if this fails.
	_, err := w.w.Write(w.buf.Bytes())
	w.buf.Reset()
	return err
}

func (w *Writer) writeFileConfig(res *Result) {
	if !w.first {
		// Configuration blocks after results get an extra blank.
		w.buf.WriteByte('\n')
		w.first = true
	}

	// Walk keys we know to find changes and deletions.
	for i := 0; i < len(w.order); i++ {
		key := w.order[i]
		have := w.fileConfig[key]
		idx, ok := res.ConfigIndex(key)
		if !ok {
			// Key was deleted.
			fmt.Fprintf(&w.buf, "%s:\n", key)
			delete(w.fileConfig, key)
			copy(w.order[i:], w.order[i+1:])
			w.order = w.order[:len(w.order)-1]
			i--
			continue
		}
		cfg := &res.Config[idx]
		if bytes.Equal(have.Value, cfg.Value) && have.File == cfg.File {
			// Value did not change.
			continue
		}
		// Value changed.
		if cfg.File {
			// Omit internal config.
			fmt.Fprintf(&w.buf, "%s: %s\n", key, cfg.Value)
		}
		have.Value = append(have.Value[:0], cfg.Value...)
		have.File = cfg.File
		w.fileConfig[key] = have
	}

	// Find new keys.
	if len(w.fileConfig) != len(res.Config) {
		for _, cfg := range res.Config {
			if _, ok := w.fileConfig[cfg.Key]; ok {
				continue
			}
			// New key.
			if cfg.File {
				fmt.Fprintf(&w.buf, "%s: %s\n", cfg.Key, cfg.Value)
			}
			w.fileConfig[cfg.Key] = Config{cfg.Key, append([]byte(nil), cfg.Value...), cfg.File}
			w.order = append(w.order, cfg.Key)
		}
	}

	w.buf.WriteByte('\n')
}
