// Copyright 2023 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 raw

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

	"internal/trace/tracev2"
	"internal/trace/version"
)

// TextReader parses a text format trace with only very basic validation
// into an event stream.
type TextReader struct {
	v     version.Version
	specs []tracev2.EventSpec
	names map[string]tracev2.EventType
	s     *bufio.Scanner
}

// NewTextReader creates a new reader for the trace text format.
func NewTextReader(r io.Reader) (*TextReader, error) {
	tr := &TextReader{s: bufio.NewScanner(r)}
	line, err := tr.nextLine()
	if err != nil {
		return nil, err
	}
	trace, line := readToken(line)
	if trace != "Trace" {
		return nil, fmt.Errorf("failed to parse header")
	}
	gover, line := readToken(line)
	if !strings.HasPrefix(gover, "Go1.") {
		return nil, fmt.Errorf("failed to parse header Go version")
	}
	rawv, err := strconv.ParseUint(gover[len("Go1."):], 10, 64)
	if err != nil {
		return nil, fmt.Errorf("failed to parse header Go version: %v", err)
	}
	v := version.Version(rawv)
	if !v.Valid() {
		return nil, fmt.Errorf("unknown or unsupported Go version 1.%d", v)
	}
	tr.v = v
	tr.specs = v.Specs()
	tr.names = tracev2.EventNames(tr.specs)
	for _, r := range line {
		if !unicode.IsSpace(r) {
			return nil, fmt.Errorf("encountered unexpected non-space at the end of the header: %q", line)
		}
	}
	return tr, nil
}

// Version returns the version of the trace that we're reading.
func (r *TextReader) Version() version.Version {
	return r.v
}

// ReadEvent reads and returns the next trace event in the text stream.
func (r *TextReader) ReadEvent() (Event, error) {
	line, err := r.nextLine()
	if err != nil {
		return Event{}, err
	}
	evStr, line := readToken(line)
	ev, ok := r.names[evStr]
	if !ok {
		return Event{}, fmt.Errorf("unidentified event: %s", evStr)
	}
	spec := r.specs[ev]
	args, err := readArgs(line, spec.Args)
	if err != nil {
		return Event{}, fmt.Errorf("reading args for %s: %v", evStr, err)
	}
	if spec.IsStack {
		len := int(args[1])
		for i := 0; i < len; i++ {
			line, err := r.nextLine()
			if err == io.EOF {
				return Event{}, fmt.Errorf("unexpected EOF while reading stack: args=%v", args)
			}
			if err != nil {
				return Event{}, err
			}
			frame, err := readArgs(line, frameFields)
			if err != nil {
				return Event{}, err
			}
			args = append(args, frame...)
		}
	}
	var data []byte
	if spec.HasData {
		line, err := r.nextLine()
		if err == io.EOF {
			return Event{}, fmt.Errorf("unexpected EOF while reading data for %s: args=%v", evStr, args)
		}
		if err != nil {
			return Event{}, err
		}
		data, err = readData(line)
		if err != nil {
			return Event{}, err
		}
	}
	return Event{
		Version: r.v,
		Ev:      ev,
		Args:    args,
		Data:    data,
	}, nil
}

func (r *TextReader) nextLine() (string, error) {
	for {
		if !r.s.Scan() {
			if err := r.s.Err(); err != nil {
				return "", err
			}
			return "", io.EOF
		}
		txt := r.s.Text()
		tok, _ := readToken(txt)
		if tok == "" {
			continue // Empty line or comment.
		}
		return txt, nil
	}
}

var frameFields = []string{"pc", "func", "file", "line"}

func readArgs(s string, names []string) ([]uint64, error) {
	var args []uint64
	for _, name := range names {
		arg, value, rest, err := readArg(s)
		if err != nil {
			return nil, err
		}
		if arg != name {
			return nil, fmt.Errorf("expected argument %q, but got %q", name, arg)
		}
		args = append(args, value)
		s = rest
	}
	for _, r := range s {
		if !unicode.IsSpace(r) {
			return nil, fmt.Errorf("encountered unexpected non-space at the end of an event: %q", s)
		}
	}
	return args, nil
}

func readArg(s string) (arg string, value uint64, rest string, err error) {
	var tok string
	tok, rest = readToken(s)
	if len(tok) == 0 {
		return "", 0, s, fmt.Errorf("no argument")
	}
	arg, val, found := strings.Cut(tok, "=")
	if !found {
		return "", 0, s, fmt.Errorf("malformed argument: %q", tok)
	}
	value, err = strconv.ParseUint(val, 10, 64)
	if err != nil {
		return arg, value, s, fmt.Errorf("failed to parse argument value %q for arg %q", val, arg)
	}
	return
}

func readToken(s string) (token, rest string) {
	tkStart := -1
	for i, r := range s {
		if r == '#' {
			return "", ""
		}
		if !unicode.IsSpace(r) {
			tkStart = i
			break
		}
	}
	if tkStart < 0 {
		return "", ""
	}
	tkEnd := -1
	for i, r := range s[tkStart:] {
		if unicode.IsSpace(r) || r == '#' {
			tkEnd = i + tkStart
			break
		}
	}
	if tkEnd < 0 {
		return s[tkStart:], ""
	}
	return s[tkStart:tkEnd], s[tkEnd:]
}

func readData(line string) ([]byte, error) {
	dk, dv, found := strings.Cut(line, "=")
	if !found || strings.TrimSpace(dk) != "data" {
		return nil, fmt.Errorf("malformed data: %q", line)
	}
	data, err := strconv.Unquote(strings.TrimSpace(dv))
	if err != nil {
		return nil, fmt.Errorf("failed to parse data: %q: %v", line, err)
	}
	return []byte(data), nil
}
