// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package main

import (
	"flag"
	"fmt"
	"path/filepath"

	"android.googlesource.com/platform/tools/gpu/client/gapis"
	"android.googlesource.com/platform/tools/gpu/framework/app"
	"android.googlesource.com/platform/tools/gpu/framework/file"
	"android.googlesource.com/platform/tools/gpu/framework/log"
	"android.googlesource.com/platform/tools/gpu/gapid/atom"
	"android.googlesource.com/platform/tools/gpu/gapid/auth"
	"android.googlesource.com/platform/tools/gpu/gapid/service"
)

var includeExtras = false

func init() {
	verb := &app.Verb{
		Name:      "dump",
		ShortHelp: "Dump a textual representation of a .gfxtrace file",
		Run:       doDump,
	}
	verb.Flags.IntVar(&gapisPort, "gapis", 0, "gapis tcp port to connect to, 0 means start new instance.")
	verb.Flags.BoolVar(&includeExtras, "extras", false, "if true then extras are also dumped.")
	verb.Run = doDump
	app.AddVerb(verb)
}

func doDump(ctx log.Context, flags flag.FlagSet) error {
	if flags.NArg() != 1 {
		app.Usage(ctx, "Exactly one gfx trace file expected, got %d", flags.NArg())
		return nil
	}

	filepath, err := filepath.Abs(flags.Arg(0))
	if err != nil {
		return fmt.Errorf("Could not find capture file '%s': %v", flags.Arg(0), err)
	}

	binDir := file.ExecutablePath().Parent()
	client, _, err := gapis.Connect(ctx, binDir, gapisPort, auth.GenToken())
	if err != nil {
		return fmt.Errorf("Failed to connect to the GAPIS server: %v", err)
	}
	defer client.(service.Client).Close(ctx)

	schema, err := client.GetSchema(ctx)
	if err != nil {
		return fmt.Errorf("Failed to load the schema: %v", err)
	}

	capture, err := client.LoadCapture(ctx, filepath)
	if err != nil {
		return fmt.Errorf("Failed to load the capture file '%v': %v", filepath, err)
	}

	boxedAtoms, err := client.Get(ctx, capture.Atoms())
	if err != nil {
		return fmt.Errorf("Failed to acquire the capture's atoms: %v", err)
	}
	atoms := boxedAtoms.(*atom.List).Atoms

	stdout := ctx.Raw("").Writer()

	for i, a := range atoms {
		if dyn, ok := a.(*atom.Dynamic); ok {
			fmt.Fprintf(stdout, "%.6d %v\n", i, dyn.StringWithConstants(schema.Constants))
		} else {
			fmt.Fprintf(stdout, "%.6d %v\n", i, a)
		}
		if includeExtras {
			extras := a.Extras()
			for _, e := range extras {
				fmt.Fprintf(stdout, "       %v\n", e)
			}
		}
	}

	return nil
}
