// Copyright 2025 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 testtrace

import (
	"flag"
	"fmt"
	"internal/trace/raw"
	"io"
	"os"
	"testing"
)

var (
	convert = flag.String("convert", "", "Path to trace text file to convert to binary format")
	output  = flag.String("out", "", "Output path for converted trace")
)

// TestConvertDump is not actually a test, it is a tool for converting trace
// text dumps generated by Dump into the binary trace format. Set -convert and
// -o to perform a converison.
//
//	go test internal/trace/testtrace -convert in.tracetxt -out out.trace
//
// This would be cleaner as a dedicated internal command rather than a test,
// but cmd/dist does not handle internal (non-distributed) commands in std
// well.
func TestConvertDump(t *testing.T) {
	if *convert == "" {
		t.Skip("Set -convert to convert a trace text file")
	}
	if *output == "" {
		t.Fatal("Set -out to specify conversion output")
	}

	if err := convertDump(*convert, *output); err != nil {
		t.Error(err)
	}
}

func convertDump(inPath, outPath string) error {
	in, err := os.Open(inPath)
	if err != nil {
		return fmt.Errorf("error opening input: %v", err)
	}
	defer in.Close()

	out, err := os.Create(outPath)
	if err != nil {
		return fmt.Errorf("error creating output: %v", err)
	}
	defer out.Close()

	tr, err := raw.NewTextReader(in)
	if err != nil {
		return fmt.Errorf("error creating text reader: %v", err)
	}
	tw, err := raw.NewWriter(out, tr.Version())
	if err != nil {
		return fmt.Errorf("error creating raw writer: %v", err)
	}

	for {
		ev, err := tr.ReadEvent()
		if err == io.EOF {
			break
		}
		if err != nil {
			return fmt.Errorf("bad trace file: %v", err)
		}
		if err := tw.WriteEvent(ev); err != nil {
			return fmt.Errorf("failed to write trace bytes: %v", err)
		}
	}

	return nil
}
