// 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"
	"io"
	"time"

	"github.com/golang/glog"
)

// An Instance is a specific combination of build, connector, and launcher,
// representable by a handle.  Most methods of this interface map directly to
// the ClusterFuchsia API.
type Instance interface {
	Start() error
	Stop() error
	ListFuzzers() []string
	Get(fuzzerName, targetSrc, hostDst string) error
	Put(fuzzerName, hostSrc, targetDst string) error
	RunFuzzer(out io.Writer, name string, args ...string) error
	Handle() (Handle, error)
	Close()
}

// BaseInstance groups the core subobjects, to which most work will be delegated
type BaseInstance struct {
	Build     Build
	Connector Connector
	Launcher  Launcher
}

// NewInstance creates a fresh instance
func NewInstance() (Instance, error) {
	build, err := NewBuild()
	if err != nil {
		return nil, fmt.Errorf("Error configuring build: %s", err)
	}

	if err := build.Prepare(); err != nil {
		return nil, fmt.Errorf("Error preparing build: %s", err)
	}

	// TODO(fxbug.dev/47479): should the user be able to choose connector/launcher types?
	launcher := NewQemuLauncher(build)

	// Note: We can't get a Connector until the Launcher has started
	return &BaseInstance{build, nil, launcher}, nil
}

func loadInstanceFromHandle(handle Handle) (Instance, error) {
	// TODO(fxbug.dev/47320): Store build info in the handle too
	build, err := NewBuild()
	if err != nil {
		return nil, fmt.Errorf("Error configuring build: %s", err)
	}

	connector, err := loadConnectorFromHandle(handle)
	if err != nil {
		return nil, err
	}

	launcher, err := loadLauncherFromHandle(build, handle)
	if err != nil {
		return nil, err
	}

	return &BaseInstance{build, connector, launcher}, nil
}

// Close releases the Instance, but doesn't Stop it
func (i *BaseInstance) Close() {
	i.Connector.Close()
}

// Start boots up the instance and waits for connectivity to be established
func (i *BaseInstance) Start() error {
	conn, err := i.Launcher.Start()
	if err != nil {
		return err
	}
	i.Connector = conn

	glog.Infof("Waiting for connectivity...")

	sleep := 3 * time.Second
	success := false
	for i := 0; i < 3; i++ {
		cmd := conn.Command("echo", "hello")
		cmd.SetTimeout(5 * time.Second)
		if err := cmd.Start(); err != nil {
			return err
		}

		if err := cmd.Wait(); err != nil {
			// If you forgot to --with-base the devtools:
			// error: 2 (/boot/bin/sh: 1: Cannot create child process: -1 (ZX_ERR_INTERNAL):
			// failed to resolve fuchsia-pkg://fuchsia.com/ls#bin/ls
			glog.Warningf("Got error during attempt %d: %s", i, err)
			glog.Warningf("Retrying in %s...", sleep)
			time.Sleep(sleep)
		} else {
			glog.Info("Instance is now online.")
			success = true

			if sc, ok := conn.(*SSHConnector); ok {
				glog.Infof("Access via: ssh -i'%s' %s:%d", sc.Key, sc.Host, sc.Port)
			}
			break
		}
	}
	if !success {
		return fmt.Errorf("error establishing connectivity to instance")
	}

	return nil
}

// RunFuzzer runs the named fuzzer on the Instance
func (i *BaseInstance) RunFuzzer(out io.Writer, name string, args ...string) error {
	fuzzer, err := i.Build.Fuzzer(name)
	if err != nil {
		return err
	}
	fuzzer.Parse(args)
	// TODO(fxbug.dev/47370): implement artifact fetching
	return fuzzer.Run(i.Connector, out, "implementMe")
}

// Get copies files from a fuzzer namespace on the Instance to the host
func (i *BaseInstance) Get(fuzzerName, targetSrc, hostDst string) error {
	fuzzer, err := i.Build.Fuzzer(fuzzerName)
	if err != nil {
		return err
	}
	return i.Connector.Get(fuzzer.AbsPath(targetSrc), hostDst)
}

// Put copies files from the host to a fuzzer namespace on the Instance
func (i *BaseInstance) Put(fuzzerName, hostSrc, targetDst string) error {
	fuzzer, err := i.Build.Fuzzer(fuzzerName)
	if err != nil {
		return err
	}
	return i.Connector.Put(hostSrc, fuzzer.AbsPath(targetDst))
}

// Stop shuts down the Instance
func (i *BaseInstance) Stop() error {
	return i.Launcher.Kill()
}

// Handle returns a Handle representing the Instance
func (i *BaseInstance) Handle() (Handle, error) {
	handle, err := NewHandleFromObjects(i.Connector, i.Launcher)
	if err != nil {
		return nil, fmt.Errorf("error constructing instance handle: %s", err)
	}

	return handle, nil
}

// ListFuzzers lists fuzzers available on the Instance
func (i *BaseInstance) ListFuzzers() []string {
	return i.Build.ListFuzzers()
}
