// Copyright 2021 The Fuchsia 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 e2e

import (
	"context"
	"errors"
	"flag"
	"log"
	"os"
	"os/exec"
	"path/filepath"
	"sync"
	"testing"

	"go.fuchsia.dev/fuchsia/tools/botanist/constants"
	"go.fuchsia.dev/fuchsia/tools/fvdl/e2e/e2etest"
	"go.fuchsia.dev/fuchsia/tools/lib/ffxutil"
)

var (
	aemuDir           = flag.String("aemu_dir", "", "Path to AEMU directory")
	grpcWebProxyDir   = flag.String("grpcwebproxy_dir", "", "Path to grpcwebproxy directory")
	deviceLauncherDir = flag.String("device_launcher_dir", "", "Path to device launcher directory")
	targetCPU         = flag.String("target_cpu", "", "Toolchain used to build Fuchsia image.")
	emulatorPath      string
	fvdl              string
	deviceLauncher    string
	grpcwebproxyPath  string
	fuchsiaBuildDir   string
	hostToolsDir      string
	ffx               string
	ffxInstance       *ffxutil.FFXInstance
	fvm               string
	zbi               string
	kernel            string
	runtimeDir        string
	amberFiles        string
	setupOnce         sync.Once
)

func setUp(t *testing.T, intree bool) {
	setupOnce.Do(func() {
		var err error

		deviceLauncher = *deviceLauncherDir
		if _, err := os.Stat(deviceLauncher); os.IsNotExist(err) {
			t.Fatalf("Invalid vdl path %q err: %s", deviceLauncher, err)
		}
		if emulatorPath = e2etest.FindFileFromDir(*aemuDir, "emulator"); emulatorPath == "" {
			t.Fatalf("Cannot find emulator binary from %q", runtimeDir)
		}
		if grpcwebproxyPath = e2etest.FindFileFromDir(*grpcWebProxyDir, "grpcwebproxy"); grpcwebproxyPath == "" {
			t.Fatalf("Cannot find grpcwebproxy binary from %q", runtimeDir)
		}

		ex, err := os.Executable()
		if err != nil {
			t.Fatal(err)
		}
		exDir := filepath.Dir(ex)

		runtimeDir = e2etest.FindDirFromDir(exDir, "fvdl_test_runtime_deps")
		if len(runtimeDir) == 0 {
			t.Fatalf("Cannot find fvdl_test_runtime_deps binary from %s", exDir)
		}
		t.Logf("[test info] fuchsia_build_dir %s", exDir)
		t.Logf("[test info] fvdl_test_runtime_deps %s", runtimeDir)
		hostToolsDir = filepath.Join(runtimeDir, "host_tools")
		if _, err := os.Stat(hostToolsDir); os.IsNotExist(err) {
			t.Fatalf("Invalid host tools dir %q err: %s", hostToolsDir, err)
		}
		fvdl = filepath.Join(hostToolsDir, "fvdl")
		if _, err := os.Stat(fvdl); os.IsNotExist(err) {
			t.Fatal(err)
		}
		ffx = filepath.Join(hostToolsDir, "ffx")
		if _, err := os.Stat(ffx); os.IsNotExist(err) {
			t.Fatal(err)
		}
		fuchsiaBuildDir = filepath.Join(runtimeDir, "images")
		if _, err := os.Stat(fuchsiaBuildDir); os.IsNotExist(err) {
			t.Fatalf("Invalid fuchsia build dir %q err: %s", fuchsiaBuildDir, err)
		}
		zbi = filepath.Join(fuchsiaBuildDir, "fuchsia.zbi")
		if _, err := os.Stat(zbi); os.IsNotExist(err) {
			t.Fatal(err)
		}
		fvm = filepath.Join(fuchsiaBuildDir, "fvm.blk")
		if _, err := os.Stat(fvm); os.IsNotExist(err) {
			t.Fatal(err)
		}
		kernel = filepath.Join(fuchsiaBuildDir, "multiboot.bin")
		if _, err := os.Stat(kernel); os.IsNotExist(err) {
			t.Fatal(err)
		}
		packages := filepath.Join(fuchsiaBuildDir, "packages.tar.gz")
		if _, err := os.Stat(packages); os.IsNotExist(err) {
			t.Fatal(err)
		}
		if err := os.Mkdir(filepath.Join(runtimeDir, ".jiri_root"), 0o755); err != nil && !os.IsExist(err) {
			t.Fatal(err)
		}
		if err := e2etest.ExtractPackage(packages, fuchsiaBuildDir); err != nil {
			t.Fatal(err)
		}
		amberFiles = filepath.Join(fuchsiaBuildDir, "amber-files")
		if intree {
			if err := e2etest.GenerateFakeArgsFile(filepath.Join(fuchsiaBuildDir, "args.gn")); err != nil {
				t.Fatal(err)
			}
			if err := e2etest.GenerateFakeImagesJson(filepath.Join(fuchsiaBuildDir, "images.json")); err != nil {
				t.Fatal(err)
			}
		}
		e2etest.CreateSSHKeyPairFiles(runtimeDir)
	})
}

// runVDLWithArgs runs fvdl, if intree, use environment variables to set tools and image path.
// if not intree, images will be downloaded from GCS.
func runVDLWithArgs(ctx context.Context, t *testing.T, args []string, intree bool) string {
	testOut, ok := os.LookupEnv("FUCHSIA_TEST_OUTDIR")
	if !ok {
		testOut = t.TempDir()
	}
	if err := os.MkdirAll(filepath.Join(testOut, t.Name()), 0o755); err != nil {
		t.Fatal(err)
	}
	// Create a new isolated ffx instance.
	ffxInstance, err := ffxutil.NewFFXInstance(ffx, "", os.Environ(), os.Getenv(constants.NodenameEnvKey), os.Getenv(constants.SSHKeyEnvKey), testOut)
	if err != nil {
		t.Fatal(err)
	}
	ffxConfigPath := filepath.Join(testOut, "ffx_config.json")
	vdlOut := filepath.Join(testOut, t.Name(), "vdl_out")
	t.Logf("[test info] writing vdl output to %s", vdlOut)
	td := t.TempDir()

	t.Cleanup(func() {
		killEmu(ctx, t, intree, vdlOut)
		if ffxInstance != nil {
			if err := ffxInstance.Stop(); err != nil {
				t.Logf("FFX didn't stop the running daemon %s", err)
			}
		}
	})

	maxTries := 2

	for tries := 0; tries < maxTries; tries++ {
		cmd := exec.CommandContext(
			ctx,
			fvdl,
			append(
				args,
				"--vdl-output", vdlOut,
				"--emulator-log", filepath.Join(testOut, t.Name(), "emu_log"),
				"--amber-unpack-root", filepath.Join(td, "packages"),
				"--isolated-ffx-config-path", ffxConfigPath,
			)...,
		)
		if intree {
			cmd.Env = append(
				os.Environ(),
				"FUCHSIA_BUILD_DIR="+fuchsiaBuildDir,
				"FUCHSIA_ZBI_COMPRESSION=zstd",
				"HOST_OUT_DIR="+hostToolsDir,
				"PREBUILT_AEMU_DIR="+mustAbs(t, emulatorPath),
				"PREBUILT_GRPCWEBPROXY_DIR="+mustAbs(t, grpcwebproxyPath),
				"PREBUILT_VDL_DIR="+mustAbs(t, deviceLauncher),
				"FVDL_INVOKER=fvdl_e2e_test",
			)
		} else {
			t.Logf("[test info] setting HOME to: %s", runtimeDir)
			// Set $HOME to runtimeDir so that fvdl can find the ssh key files, which are
			// expected in $HOME/.ssh/...
			cmd.Env = append(os.Environ(), "HOME="+runtimeDir, "FVDL_INVOKER=fvdl_e2e_test")
		}
		cmd.Dir = td
		cmd.Stdout = os.Stdout
		cmd.Stderr = os.Stderr
		if err := cmd.Run(); err != nil {
			var e *exec.ExitError
			if errors.As(err, &e) {
				// ExitCode == 1 means something went wrong with the launcher. Don't retry.
				if e.ExitCode() == 1 {
					t.Fatal(err)
				}
			}
			if tries == maxTries-1 {
				t.Fatal(err)
			}
			log.Printf("Retry launching emulator... got err %s", err)
		} else {
			break
		}
	}
	return vdlOut
}

func mustAbs(t *testing.T, p string) string {
	t.Helper()
	abs, err := filepath.Abs(p)
	if err != nil {
		t.Fatalf("Failed to convert %q to absolute path: %v", p, err)
	}
	return abs
}

// killEmu shuts down fvdl with action kill command
func killEmu(ctx context.Context, t *testing.T, intree bool, vdlOut string) {
	t.Logf("[test info] killing fvdl using proto: %s", vdlOut)
	var cmd *exec.Cmd
	if intree {
		cmd = exec.CommandContext(ctx, fvdl, "kill", "--launched-proto", vdlOut)
		cmd.Env = append(
			os.Environ(),
			"FUCHSIA_BUILD_DIR="+fuchsiaBuildDir,
			"FUCHSIA_ZBI_COMPRESSION=zstd",
			"HOST_OUT_DIR="+hostToolsDir,
			"PREBUILT_AEMU_DIR="+mustAbs(t, emulatorPath),
			"PREBUILT_GRPCWEBPROXY_DIR="+mustAbs(t, grpcwebproxyPath),
			"PREBUILT_VDL_DIR="+mustAbs(t, deviceLauncher),
			"FVDL_INVOKER=fvdl_e2e_test",
		)
	} else {
		cmd = exec.CommandContext(
			ctx,
			fvdl,
			"--sdk",
			"kill",
			"--launched-proto",
			vdlOut,
			"-d",
			mustAbs(t, filepath.Join(deviceLauncher, "device_launcher")),
		)
		cmd.Env = append(os.Environ(), "FVDL_INVOKER=fvdl_e2e_test")
	}
	cmd.Stdout = os.Stdout
	cmd.Stderr = os.Stderr
	if err := cmd.Run(); err != nil {
		t.Errorf("shutting down fvdl errored: %w", err)
	}
}
