// 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 (
	"crypto/rand"
	"crypto/rsa"
	"crypto/x509"
	"encoding/pem"
	"fmt"
	"io"
	"io/ioutil"
	"net"
	"os"
	"path"
	"path/filepath"
	"strconv"
	"strings"

	"github.com/golang/glog"
	"github.com/pkg/sftp"
	"golang.org/x/crypto/ssh"
)

// A Connector is used to communicate with an instance
type Connector interface {
	// Connect establishes all necessary connections to the instance. It does
	// not need to be explicitly called, because the other Connector methods will
	// automatically connect if necessary, but may be called during initializiation.
	// It the connector is already connected, an error will be returned.
	Connect() error

	// Close closes any open connections to the instance. It is the client's
	// responsibility to call Close() when cleaning up the Connector.
	Close()

	// Returns an InstanceCmd representing the command to be run on the instance. Only one
	// command should be active at a time.
	// TODO(fxb/47479): In some cases, we should be able to relax the above restriction
	Command(name string, args ...string) InstanceCmd

	// Copies targetSrc (may include globs) to hostDst
	Get(targetSrc, hostDst string) error

	// Copies hostSrc (may include globs) to targetDst
	Put(hostSrc, targetDst string) error

	// Retrieves a syslog from the instance, filtered to the given process ID
	GetSysLog(pid int) (string, error)
}

// An SSHConnector is a Connector that uses SSH/SFTP for transport
// Note: exported fields will be serialized to the handle
type SSHConnector struct {
	// Host can be any IP or hostname as accepted by net.Dial
	Host string
	Port int
	// Key is a path to the SSH private key that should be used for
	// authentication
	Key string

	client     *ssh.Client
	sftpClient *sftp.Client
}

// Connect to the remote server
func (c *SSHConnector) Connect() error {
	if c.client != nil {
		return fmt.Errorf("Connect called, but already connected")
	}

	glog.Info("SSH: connecting...")
	key, err := ioutil.ReadFile(c.Key)
	if err != nil {
		return fmt.Errorf("error reading ssh key: %s", err)
	}

	signer, err := ssh.ParsePrivateKey(key)
	if err != nil {
		return fmt.Errorf("error parsing ssh key: %s", err)
	}

	config := &ssh.ClientConfig{
		User: "clusterfuchsia",
		Auth: []ssh.AuthMethod{
			ssh.PublicKeys(signer),
		},
		HostKeyCallback: ssh.InsecureIgnoreHostKey(),
	}

	// TODO(fxb/45424): dial timeout
	address := net.JoinHostPort(c.Host, strconv.Itoa(c.Port))
	client, err := ssh.Dial("tcp", address, config)
	if err != nil {
		return fmt.Errorf("error connecting ssh: %s", err)
	}

	glog.Info("SSH: connected")
	c.client = client

	sftpClient, err := sftp.NewClient(c.client)
	if err != nil {
		return fmt.Errorf("error connecting sftp: %s", err)
	}

	glog.Info("SFTP: connected")
	c.sftpClient = sftpClient

	return nil
}

// Close any open connections
func (c *SSHConnector) Close() {
	glog.Info("Closing SSH/SFTP")

	// TODO(fxb/47316): Look into errors thrown by these Closes when
	// disconnecting from in-memory SSH server
	if c.client != nil {
		if err := c.client.Close(); err != nil {
			glog.Warningf("Error while closing SSH: %s", err)
		}
		c.client = nil
	}

	if c.sftpClient != nil {
		if err := c.sftpClient.Close(); err != nil {
			glog.Warningf("Error while closing SFTP: %s", err)
		}
		c.sftpClient = nil
	}
}

// Command returns an InstanceCmd that can be used to given command over SSH
func (c *SSHConnector) Command(name string, args ...string) InstanceCmd {
	// TODO(fxb/45424): Would be best to shell escape
	cmdline := strings.Join(append([]string{name}, args...), " ")
	return &SSHInstanceCmd{connector: c, cmdline: cmdline}
}

// GetSysLog will fetch the syslog by running a remote command
func (c *SSHConnector) GetSysLog(pid int) (string, error) {
	cmd := c.Command("log_listener", "--dump_logs", "yes", "--pretty", "no",
		"--pid", strconv.Itoa(pid))

	out, err := cmd.Output()
	if err != nil {
		return "", err
	}
	return string(out), nil
}

// Get fetches files over SFTP
func (c *SSHConnector) Get(targetSrc string, hostDst string) error {
	if c.sftpClient == nil {
		if err := c.Connect(); err != nil {
			return err
		}
	}

	// Expand any globs in source path
	srcList, err := c.sftpClient.Glob(targetSrc)
	if err != nil {
		return fmt.Errorf("error during glob expansion: %s", err)
	}
	if len(srcList) == 0 {
		return fmt.Errorf("no files matching glob: '%s'", targetSrc)
	}

	for _, src := range srcList {
		glog.Infof("Copying [remote]:%s to %s", src, hostDst)

		fin, err := c.sftpClient.Open(src)
		if err != nil {
			return fmt.Errorf("error opening remote file: %s", err)
		}
		defer fin.Close()
		// TODO(fxb/45429): handle non-dir dst, ensure exists, etc
		fout, err := os.Create(path.Join(hostDst, path.Base(src)))
		if err != nil {
			return fmt.Errorf("error creating local file: %s", err)
		}
		defer fout.Close()
		if _, err := io.Copy(fout, fin); err != nil {
			return fmt.Errorf("error copying file: %s", err)
		}

	}
	return nil
}

// Put uploads files over SFTP
func (c *SSHConnector) Put(hostSrc string, targetDst string) error {
	if c.sftpClient == nil {
		if err := c.Connect(); err != nil {
			return err
		}
	}

	// Expand any globs in source path
	srcList, err := filepath.Glob(hostSrc)
	if err != nil {
		return fmt.Errorf("error during glob expansion: %s", err)
	}
	if len(srcList) == 0 {
		return fmt.Errorf("no files matching glob: '%s'", hostSrc)
	}

	for _, src := range srcList {
		glog.Infof("Copying %s to [remote]:%s", src, targetDst)

		fin, err := os.Open(src)
		defer fin.Close()
		if err != nil {
			return fmt.Errorf("error opening local file: %s", err)
		}
		// TODO(fxb/45429): handle non-dir dst, ensure exists, etc
		fout, err := c.sftpClient.Create(path.Join(targetDst, path.Base(src)))
		defer fout.Close()
		if err != nil {
			return fmt.Errorf("error creating remote file: %s", err)
		}
		if _, err := io.Copy(fout, fin); err != nil {
			return fmt.Errorf("error copying file: %s", err)
		}

	}
	return nil
}

func loadConnectorFromHandle(handle Handle) (Connector, error) {
	// TODO(fxb/47479): detect connector type
	var conn SSHConnector

	if err := handle.PopulateObject(&conn); err != nil {
		return nil, err
	}

	if conn.Host == "" {
		return nil, fmt.Errorf("host not found in handle")
	}
	if conn.Port == 0 {
		return nil, fmt.Errorf("port not found in handle")
	}
	if conn.Key == "" {
		return nil, fmt.Errorf("key not found in handle")
	}

	return &conn, nil
}

// Generate a key to use for SSH
// TODO(fxb/45424): Also return public key
func createSSHKey() (*rsa.PrivateKey, error) {
	privKey, err := rsa.GenerateKey(rand.Reader, 2048)
	if err != nil {
		return nil, fmt.Errorf("error generating keypair: %s", err)
	}

	return privKey, nil
}

// Writes private key to given path in format usable by SSH
func writeSSHPrivateKeyFile(key *rsa.PrivateKey, path string) error {
	pemData := pem.EncodeToMemory(&pem.Block{
		Type:  "RSA PRIVATE KEY",
		Bytes: x509.MarshalPKCS1PrivateKey(key),
	})

	if err := ioutil.WriteFile(path, pemData, 0600); err != nil {
		return fmt.Errorf("error writing private key file: %s", err)
	}

	return nil
}
