package powercycle

import (
	"fmt"
	"io/ioutil"
	"os"
	"os/user"
	"sort"
	"time"

	"go.skia.org/infra/go/sklog"
	"go.skia.org/infra/go/util"
	"golang.org/x/crypto/ssh"
)

// ArduinoConfig contains the necessary parameters to connect
// and control an Arduino with servos via the serial_relay program, that
// is assumed to run on the remote host.
type ArduinoConfig struct {
	Address    string         `json:"address"` // IP address and port of the device, i.e. 192.168.1.33:22
	DevPortMap map[string]int `json:"ports"`   // Mapping between device name and port on the power strip.
}

// ArduinoClient implements the DeviceGroup interface.
type ArduinoClient struct {
	client        *ssh.Client
	deviceIDs     []string
	arduinoConfig *ArduinoConfig
}

// NewArduinoClient returns a new instance of DeviceGroup for the
// Arduino driven servos.
func NewArduinoClient(arduinoConfig *ArduinoConfig, connect bool) (DeviceGroup, error) {
	var client *ssh.Client = nil
	if connect {
		key, err := ioutil.ReadFile(os.ExpandEnv("${HOME}/.ssh/id_rsa"))
		if err != nil {
			return nil, fmt.Errorf("Unable to read private key: %v", err)
		}
		sklog.Infof("Retrieved private key")

		// Create the Signer for this private key.
		signer, err := ssh.ParsePrivateKey(key)
		if err != nil {
			return nil, fmt.Errorf("Unable to parse private key: %v", err)
		}
		sklog.Infof("Parsed private key")

		currUser, err := user.Current()
		if err != nil {
			return nil, fmt.Errorf("Unable to retrieve current user: %s", err)
		}

		sshConfig := &ssh.ClientConfig{
			User:            currUser.Username,
			Auth:            []ssh.AuthMethod{ssh.PublicKeys(signer)},
			HostKeyCallback: ssh.InsecureIgnoreHostKey(),
		}

		sklog.Infof("Signed private key")

		client, err = ssh.Dial("tcp", arduinoConfig.Address, sshConfig)
		if err != nil {
			return nil, err
		}

		sklog.Infof("Dial successful")
	}

	devIDs := make([]string, 0, len(arduinoConfig.DevPortMap))
	for id := range arduinoConfig.DevPortMap {
		devIDs = append(devIDs, id)
	}
	sort.Strings(devIDs)

	ret := &ArduinoClient{
		client:        client,
		deviceIDs:     devIDs,
		arduinoConfig: arduinoConfig,
	}

	if connect {
		if err := ret.ping(); err != nil {
			return nil, err
		}
	}

	return ret, nil
}

// DeviceIDs, see DeviceGroup interface.
func (a *ArduinoClient) DeviceIDs() []string {
	return a.deviceIDs
}

// PowerCycle, see PowerCycle interface.
func (a *ArduinoClient) PowerCycle(devID string, delayOverride time.Duration) error {
	if !util.In(devID, a.deviceIDs) {
		return fmt.Errorf("Unknown device ID: %s", devID)
	}

	port := a.arduinoConfig.DevPortMap[devID]
	cmd := fmt.Sprintf("./serial_relay %d", port)
	session, err := a.client.NewSession()
	if err != nil {
		return err
	}
	defer util.Close(session)

	sklog.Infof("Executing: %s", cmd)
	outBytes, err := session.CombinedOutput(cmd)
	if err != nil {
		return fmt.Errorf("Error executing %s: %s\nGot output:\n%s", cmd, err, string(outBytes))
	}

	sklog.Infof("Powercycled port %s on port %d.", devID, port)
	return nil
}

// PowerUsage, see the DeviceGroup interface.
func (a *ArduinoClient) PowerUsage() (*GroupPowerUsage, error) {
	return &GroupPowerUsage{}, nil // N/A for arduino board.
}

// ping issues a command to the device to verify that the
// connection works.
func (a *ArduinoClient) ping() error {
	sklog.Infof("Executing ping.")

	session, err := a.client.NewSession()
	if err != nil {
		return err
	}
	defer util.Close(session)

	out, err := session.CombinedOutput("pwd")
	if err != nil {
		return err
	}
	sklog.Infof("PWD: %s", string(out))
	return nil
}
