// Copyright 2020 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 fuzz

import (
	"fmt"
	"os"
	"os/exec"
	"path/filepath"
	"strings"
	"testing"
)

const mockFuzzerPid = 414141

// Used for keeping history of Put/Get calls
type transferCmd struct {
	src, dst string
}

// mockConnector is used in Fuzzer and Instance tests, and returned by mockLauncher.Start()
type mockConnector struct {
	connected                bool
	shouldFailToConnectCount uint
	shouldFailToExecuteCount uint
	shouldFailToGetSysLog    bool

	ffxIsolateDir string

	// Store history of Get/Puts to enable basic checks
	PathsGot           []transferCmd
	PathsPut           []transferCmd
	LastPutFileContent string

	// List of paths for which IsDir() should return true
	Dirs []string

	// Store history of commands run on this connection
	CmdHistory     []string
	FuzzCtlHistory []string
	FfxHistory     []string

	CleanedUp bool
}

func NewMockConnector(t *testing.T) *mockConnector {
	return &mockConnector{ffxIsolateDir: t.TempDir()}
}

func (c *mockConnector) Connect() error {
	if c.connected {
		return fmt.Errorf("Connect called when already connected")
	}

	if c.shouldFailToConnectCount > 0 {
		c.shouldFailToConnectCount -= 1
		return fmt.Errorf("Intentionally broken Connector")
	}

	c.connected = true
	return nil
}

func (c *mockConnector) Close() {
	c.connected = false
}

func (c *mockConnector) RmDir(path string) error {
	return c.Command("rm", "-rf", path).Run()
}

func (c *mockConnector) IsDir(path string) (bool, error) {
	if strings.HasSuffix(path, invalidPath) {
		return false, os.ErrNotExist
	}

	for _, dir := range c.Dirs {
		if path == dir {
			return true, nil
		}
	}
	return false, nil
}

func (c *mockConnector) Cleanup() {
	c.CleanedUp = true
}

func (c *mockConnector) Command(name string, args ...string) InstanceCmd {
	shouldFail := c.shouldFailToExecuteCount > 0
	if shouldFail {
		c.shouldFailToExecuteCount -= 1
	}
	return &mockInstanceCmd{connector: c, name: name, args: args, shouldFail: shouldFail}
}

func (c *mockConnector) Get(targetSrc string, hostDst string) error {
	fileInfo, err := os.Stat(hostDst)
	if err != nil {
		return fmt.Errorf("error stat-ing dest %q: %s", hostDst, err)
	}

	if !fileInfo.IsDir() {
		return fmt.Errorf("host dest is not a dir")
	}

	c.PathsGot = append(c.PathsGot, transferCmd{targetSrc, hostDst})

	return nil
}

func (c *mockConnector) Put(hostSrc string, targetDst string) error {
	srcList, err := filepath.Glob(hostSrc)
	if err != nil {
		return fmt.Errorf("error globbing source %q: %s", hostSrc, err)
	}

	if len(srcList) == 0 {
		return fmt.Errorf("no matches for glob %q", hostSrc)
	}

	for _, src := range srcList {
		fileInfo, err := os.Stat(src)
		if err != nil {
			return fmt.Errorf("error stat-ing source %q: %s", src, err)
		}

		// If a file was Put, save its contents
		if !fileInfo.IsDir() {
			data, err := os.ReadFile(src)
			if err != nil {
				return fmt.Errorf("error reading file: %s", err)
			}

			c.LastPutFileContent = string(data)
		}

		c.PathsPut = append(c.PathsPut, transferCmd{src, targetDst})
	}

	return nil
}

func (c *mockConnector) GetSysLog(pid int) (string, error) {
	if c.shouldFailToGetSysLog {
		return "syslog failure", fmt.Errorf("Intentionally broken Connector")
	}

	// Only return logs for the PID we expect
	if pid != mockFuzzerPid {
		return "", nil
	}

	// TODO(https://fxbug.dev/42121948): more realistic test data
	lines := []string{
		fmt.Sprintf("syslog for %d", pid),
		"[1234.5][klog] INFO: {{{0x41}}}",
	}
	return strings.Join(lines, "\n"), nil
}

func (c *mockConnector) FfxRun(outputDir string, args ...string) (string, error) {
	c.FfxHistory = append(c.FfxHistory, strings.Join(args, " "))
	return strings.Join(args, " "), nil
}

// Whether, based on PathsPut, the target path should exist (assumes only files are put)
func (c *mockConnector) TargetPathExists(path string) bool {
	for _, put := range c.PathsPut {
		targetPath := filepath.Join(put.dst, filepath.Base(put.src))
		if targetPath == path {
			return true
		}
	}
	return false
}

func (c *mockConnector) FfxCommand(outputDir string, args ...string) (*exec.Cmd, error) {
	// Used only by Fuzzer.Run, which needs a full subprocess to work with
	args = append([]string{"--target", "some-target",
		"--isolate-dir", c.ffxIsolateDir}, args...)
	if outputDir != "" {
		args = append(args, "-o", outputDir)
	}

	// Instead of fully rewriting cache paths, which is impossible since we
	// don't implement an actual cache here, just set any unknown ones to an
	// invalidPath.
	for j, arg := range args {
		if !strings.HasPrefix(arg, cachePrefix) {
			continue
		}
		if !c.TargetPathExists(arg) {
			args[j] = invalidPath
		}
	}

	cmd := mockCommand("ffx", args...)
	return cmd, nil
}
