// 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"
	"io/ioutil"
	"os"
	"path/filepath"
	"regexp"
	"runtime"
	"time"

	"android.googlesource.com/platform/tools/gpu/client/adb"
	"android.googlesource.com/platform/tools/gpu/client/android"
	"android.googlesource.com/platform/tools/gpu/client/android/apk"
	"android.googlesource.com/platform/tools/gpu/client/bind"
	"android.googlesource.com/platform/tools/gpu/client/gapii"
	"android.googlesource.com/platform/tools/gpu/client/process"
	"android.googlesource.com/platform/tools/gpu/framework/app"
	"android.googlesource.com/platform/tools/gpu/framework/device"
	"android.googlesource.com/platform/tools/gpu/framework/file"
	"android.googlesource.com/platform/tools/gpu/framework/log"
	"android.googlesource.com/platform/tools/gpu/framework/task"
	"android.googlesource.com/platform/tools/gpu/gapid/pkgdata"
)

var (
	targetDevice    string
	duration        time.Duration
	output          string
	localPort       int
	localApp        file.Path
	observeFrames   uint
	observeDraws    uint
	disablePCS      bool
	recordErrors    bool
	clearCache      bool
	inputFile       string
	recordInputs    bool
	replayInputs    bool
	useLDPreload    bool
	apkPath         file.Path
	interceptorPath file.Path
	gapiiPath       file.Path
	vulkanLayerPath file.Path
)

func init() {
	verb := &app.Verb{
		Name:      "trace",
		ShortHelp: "Captures a gfx trace from an application",
		Run:       doTrace,
	}
	verb.Flags.StringVar(&targetDevice, "device", "", "the device to capture on")
	verb.Flags.DurationVar(&duration, "d", 0, "duration to trace for")
	verb.Flags.StringVar(&output, "out", "", "the file to generate")
	verb.Flags.IntVar(&localPort, "local", 0, "capture a local program instead of using ADB")
	verb.Flags.Var(&localApp, "local-app", "a local program to trace")
	verb.Flags.UintVar(&observeFrames, "observe-frames", 0, "capture the framebuffer every n frames (0 to disable)")
	verb.Flags.UintVar(&observeDraws, "observe-draws", 0, "capture the framebuffer every n draws (0 to disable)")
	verb.Flags.BoolVar(&disablePCS, "disable-pcs", false, "disable pre-compiled shaders")
	verb.Flags.BoolVar(&recordErrors, "record-errors", false, "record device error state")
	verb.Flags.BoolVar(&clearCache, "clear-cache", false, "clear package data before running it")
	verb.Flags.StringVar(&inputFile, "input-file", "", "the file to use for recorded inputs")
	verb.Flags.BoolVar(&recordInputs, "record-inputs", false, "record the inputs to file")
	verb.Flags.BoolVar(&replayInputs, "replay-inputs", false, "replay the inputs from file")
	verb.Flags.BoolVar(&useLDPreload, "ld-preload", false, "use LD_PRELOAD to register the interceptor library")
	verb.Flags.Var(&apkPath, "apk", "the path to an apk to install")
	verb.Flags.Var(&interceptorPath, "interceptor", "the path to the interceptor library")
	verb.Flags.Var(&gapiiPath, "gapii", "the path to the gapii library")
	verb.Flags.Var(&vulkanLayerPath, "vulkan-layer", "the path to the vulkan trace layer library")
	app.AddVerb(verb)
}

func doTrace(ctx log.Context, flags flag.FlagSet) error {
	options := gapii.Options{
		ObserveFrameFrequency: uint32(observeFrames),
		ObserveDrawFrequency:  uint32(observeDraws),
		APK:                   apkPath,
		Interceptor:           interceptorPath,
		Gapii:                 gapiiPath,
		VkLayer:               vulkanLayerPath,
	}

	if disablePCS {
		options.Flags |= gapii.DisablePrecompiledShaders
	}
	if recordErrors {
		options.Flags |= gapii.RecordErrorState
	}

	if !localApp.IsEmpty() {
		// Run the local application with VK_LAYER_PATH, VK_INSTANCE_LAYERS,
		// VK_DEVICE_LAYERS and LD_PRELOAD set to correct values to load the spy
		// layer.
		localAbi := device.UnknownABI
		switch runtime.GOOS {
		case "linux":
			localAbi = device.LinuxX86_64
		default:
			return fmt.Errorf("Unsupported OS for local tracing")
		}

		var err error
		if vulkanLayerPath.IsEmpty() {
			vulkanLayerPath, err = pkgdata.File(ctx, localAbi, "LibVkLayerGraphicsSpy.so")
		}
		if err != nil {
			return err
		}
		if gapiiPath.IsEmpty() {
			// TODO (qining): library name may change for different OS/ABI
			gapiiPath, err = pkgdata.File(ctx, localAbi, "libgapii.so")
		}
		if err != nil {
			return err
		}
		libGapiiDirStr := filepath.Dir(gapiiPath.String())
		libGapiiPathStr := filepath.Join(libGapiiDirStr, "libgapii.so")
		vulkanLayerDirStr := filepath.Dir(vulkanLayerPath.String())

		os.Setenv("VK_LAYER_PATH", vulkanLayerDirStr)
		os.Setenv("VK_INSTANCE_LAYERS", "VkGraphicsSpy")
		os.Setenv("VK_DEVICE_LAYERS", "VkGraphicsSpy")
		os.Setenv("LD_PRELOAD", libGapiiPathStr)
		boundPort, err := process.Start(ctx, localApp.String())
		if err != nil {
			return err
		}
		if localPort == 0 {
			localPort = boundPort
		}
	}

	if localPort != 0 {
		return captureLocal(ctx, flags, localPort, options)
	}

	return captureADB(ctx, flags, options, useLDPreload)
}

func captureLocal(ctx log.Context, flags flag.FlagSet, port int, options gapii.Options) error {
	if output == "" {
		output = "capture.gfxtrace"
	}
	return capture(ctx, options, port, output)
}

// gapiiABI returns the ABI-flavor of GAPII to use given the device and package.
func gapiiABI(ctx log.Context, d bind.Device, info *apk.Information) device.ABI {
	for _, preferred := range d.Info().Configuration.ABIs {
		for _, abi := range info.ABI {
			if device.SameABI(preferred, *abi) {
				return preferred
			}
		}
	}
	return d.ABI() // Meh.
}

func captureADB(ctx log.Context, flags flag.FlagSet, options gapii.Options, useLDPreload bool) error {
	d, err := getADBDevice(ctx, targetDevice)
	if err != nil {
		return err
	}
	var a *android.Action
	if !options.APK.IsEmpty() {
		ctx.V("Source", options.APK).Print("Installing APK")
		data, err := ioutil.ReadFile(options.APK.System())
		if err != nil {
			return ctx.WrapError(err, "Read APK")
		}
		info, err := apk.Analyze(ctx, data)
		if err != nil {
			return ctx.WrapError(err, "Analyse APK")
		}
		if err := d.InstallAPK(ctx, options.APK.System(), true, true); err != nil {
			return ctx.WrapError(err, "Install APK")
		}
		pkg := &android.InstalledPackage{
			Name:       info.Name,
			Device:     d,
			ABI:        gapiiABI(ctx, d, info),
			Debuggable: info.Debuggable,
		}
		defer func() {
			ctx.Notice().V("apk", options.APK).Log("Uninstall APK")
			pkg.Uninstall(ctx)
		}()
		a = &android.Action{
			Name:     info.Action,
			Package:  pkg,
			Activity: info.Activity,
		}
	} else {
		if flags.NArg() != 1 {
			app.Usage(ctx, "Invalid number of arguments. Expected 1, got %d", flags.NArg())
			return nil
		}
		activity := flags.Arg(0)
		a, err = getAction(ctx, d, activity)
		if err != nil {
			return err
		}
	}

	if !useLDPreload && a.Package.Debuggable {
		ctx.Print("Package is debuggable")
	} else {
		err = d.Root(ctx)
		switch err {
		case nil:
		case adb.ErrDeviceNotRooted:
			return err
		default:
			return fmt.Errorf("Failed to restart ADB as root: %v", err)
		}
		ctx.Print("Device is rooted")
	}

	// Filenames - if no name specified, use package name.
	if output == "" {
		output = a.Package.Name + ".gfxtrace"
	}
	if inputFile == "" {
		inputFile = a.Package.Name + ".inputs"
	}

	if clearCache {
		ctx.Print("Clearing package cache")
		if err := a.Package.ClearCache(ctx); err != nil {
			return err
		}
	}

	if wasScreenOn, _ := d.IsScreenOn(ctx); !wasScreenOn {
		defer d.TurnScreenOff(ctx) // Think green!
	}

	start := gapii.JdwpStart
	if useLDPreload {
		start = gapii.AdbStart
	}

	libraries := gapii.NewLibraries()
	libraries.Set(gapii.LibInterceptor, options.Interceptor)
	libraries.Set(gapii.LibGapii, options.Gapii)
	libraries.Set(gapii.LibVkLayer, options.VkLayer)
	if err := libraries.Find(ctx, a); err != nil {
		return err
	}
	port, cleanup, err := start(ctx, libraries, a)
	if err != nil {
		return err
	}
	defer cleanup(ctx)

	ctx, stop := task.WithCancel(ctx)
	if recordInputs {
		ctx.Print("Starting input recorder")
		cleanup, err := startRecordingInputs(ctx, d, inputFile)
		if err != nil {
			return err
		}
		defer cleanup()
	} else if replayInputs {
		ctx.Print("Starting input replayer")
		if err := startReplayingInputs(ctx, d, inputFile, stop); err != nil {
			return err
		}
	}

	return capture(ctx, options, int(port), output)
}

func capture(ctx log.Context, options gapii.Options, port int, out string) error {
	ctx.Info().S("file", out).Log("Creating file")
	os.MkdirAll(filepath.Dir(out), 0755)
	file, err := os.Create(out)
	if err != nil {
		return err
	}
	defer file.Close()

	if duration == 0 {
		var cancel task.CancelFunc
		ctx, cancel = task.WithCancel(ctx)
		go func() {
			println("Press enter to stop capturing...")
			os.Stdin.Read([]byte{0})
			cancel()
		}()
	} else {
		ctx, _ = task.WithTimeout(ctx, duration)
	}
	_, err = gapii.Capture(ctx, port, file, options)
	if err != nil {
		return err
	}
	return nil
}

func getAction(ctx log.Context, d adb.Device, pattern string) (*android.Action, error) {
	re := regexp.MustCompile("(?i)" + pattern)
	packages, err := d.InstalledPackages(ctx)
	if err != nil {
		return nil, err
	}
	if len(packages) == 0 {
		return nil, fmt.Errorf("No packages found")
	}
	matchingActions := []*android.Action{}
	for _, p := range packages {
		for _, action := range p.Actions {
			if re.MatchString(action.String()) {
				matchingActions = append(matchingActions, action)
			}
		}
	}
	if len(matchingActions) == 0 {
		return nil, fmt.Errorf("No actions matching %s found", pattern)
	} else if len(matchingActions) > 1 {
		fmt.Println("Matching actions:")
		for _, test := range matchingActions {
			fmt.Print("    ")
			fmt.Println(test)
		}
		return nil, fmt.Errorf("Multiple actions matching %q found", pattern)
	}
	ctx.Info().WithValue("action", matchingActions[0]).Log("")
	return matchingActions[0], nil
}
