// Copyright 2019 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 devices

import (
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net"
	"time"

	"go.fuchsia.dev/fuchsia/tools/net/serial"

	"golang.org/x/crypto/ssh"
)

const (
	// The duration we allow for the netstack to come up when booting.
	netstackTimeout = 90 * time.Second
)

type DeviceType string

// DeviceConfig contains the static properties of a target device.
type DeviceConfig struct {
	// Type tells us what kind of machine this is.
	Type string `json:"type"`

	// Network is the network properties of the target.
	Network NetworkProperties `json:"network"`

	// Power is the attached power management configuration.
	Power *PowerClient `json:"power,omitempty"`

	// SSHKeys are the default system keys to be used with the device.
	SSHKeys []string `json:"keys,omitempty"`

	// Serial is the path to the device file for serial i/o.
	Serial string `json:"serial,omitempty"`
}

// NetworkProperties are the static network properties of a target.
type NetworkProperties struct {
	// Nodename is the hostname of the device that we want to boot on.
	Nodename string `json:"nodename"`

	// IPv4Addr is the IPv4 address, if statically given. If not provided, it may be
	// resolved via the netstack's MDNS server.
	IPv4Addr string `json:"ipv4"`

	// Mac is the mac address of the device
	Mac string `json:"mac"`
}

// LoadDeviceConfigs unmarshalls a slice of device configs from a given file.
func LoadDeviceConfigs(path string) ([]DeviceConfig, error) {
	data, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, fmt.Errorf("failed to read device properties file %q", path)
	}

	var configs []DeviceConfig
	if err := json.Unmarshal(data, &configs); err != nil {
		return nil, fmt.Errorf("failed to unmarshal configs: %v", err)
	}
	return configs, nil
}

// DeviceTarget represents a target device.
type DeviceTarget struct {
	deviceType    DeviceType
	config        DeviceConfig
	signers       []ssh.Signer
	serial        io.ReadWriteCloser
	BootserverCmd []string
}

// CreateDeviceTargets loads configs from the given file and creates DeviceTargets for each one
func CreateDeviceTargets(ctx context.Context, path string, bootserverCmdStub []string) ([]*DeviceTarget, error) {
	deviceConfigs, err := LoadDeviceConfigs(path)
	if err != nil {
		return nil, err
	}
	var devices []*DeviceTarget
	for _, deviceConfig := range deviceConfigs {
		device, err := NewDeviceTarget(ctx, deviceConfig, bootserverCmdStub)
		if err != nil {
			return nil, err
		}
		devices = append(devices, device)
	}
	return devices, nil
}

// NewDeviceTarget returns a new device target with a given configuration.
func NewDeviceTarget(ctx context.Context, config DeviceConfig, bootserverCmdStub []string) (*DeviceTarget, error) {
	signers, err := parseOutSigners(config.SSHKeys)
	if err != nil {
		return nil, fmt.Errorf("could not parse out signers from private keys: %v", err)
	}
	var s io.ReadWriteCloser
	if config.Serial != "" {
		s, err = serial.Open(config.Serial)
		if err != nil {
			log.Printf("unable to open %s: %v", config.Serial, err)
		}
	}
	deviceType, err := ConvertConfigType(config)
	if err != nil {
		return nil, err
	}
	return &DeviceTarget{
		deviceType:    deviceType,
		config:        config,
		signers:       signers,
		serial:        s,
		BootserverCmd: append(bootserverCmdStub, config.Network.Nodename),
	}, nil
}

// ConvertConfigType converts a device type from the configs into a more
// manageable representation.
func ConvertConfigType(config DeviceConfig) (DeviceType, error) {
	switch config.Type {
	case "Intel NUC Kit NUC7i5DNHE":
		return "nuc", nil
	case "Khadas Vim2 Max":
		return "vim2", nil
	case "Astro":
		return "astro", nil
	case "Sherlock":
		return "sherlock", nil
	case "Nelson":
		return "nelson", nil
	}
	return "", fmt.Errorf("Invalid device type in configs: %s", config.Type)
}

// SetConfig sets the config field of the given DeviceTarget
func (t *DeviceTarget) SetConfig(config DeviceConfig) {
	t.config = config
}

// Nodename returns the name of the node.
func (t *DeviceTarget) Nodename() string {
	return t.config.Network.Nodename
}

// IPv4Addr returns the IPv4 address of the node from the config
func (t *DeviceTarget) IPv4Addr() (net.IP, error) {
	return net.ParseIP(t.config.Network.IPv4Addr), nil
}

// Mac returns the Mac address of the node from the config
func (t *DeviceTarget) Mac() string {
	return t.config.Network.Mac
}

// Serial returns the serial device associated with the target for serial i/o.
func (t *DeviceTarget) Serial() io.ReadWriteCloser {
	return t.serial
}

// Type returns the type of the device.
func (t *DeviceTarget) Type() DeviceType {
	return t.deviceType
}

// Restart restarts the target.
func (t *DeviceTarget) Restart(ctx context.Context) error {
	if t.serial != nil {
		defer t.serial.Close()
	}
	if t.config.Power != nil {
		if err := t.config.Power.RebootDevice(t.signers, t.Nodename(), t.serial); err != nil {
			return fmt.Errorf("failed to reboot the device: %v", err)
		}
	}
	return nil
}

// Powercycle uses an out of band method to powercycle the target.
func (t *DeviceTarget) Powercycle(ctx context.Context) error {
	if t.config.Power != nil {
		return t.config.Power.Powercycle(t.Nodename(), t.Mac(), t.serial)
	}
	return nil
}

func parseOutSigners(keyPaths []string) ([]ssh.Signer, error) {
	if len(keyPaths) == 0 {
		return nil, errors.New("must supply SSH keys in the config")
	}
	var keys [][]byte
	for _, keyPath := range keyPaths {
		p, err := ioutil.ReadFile(keyPath)
		if err != nil {
			return nil, fmt.Errorf("could not read SSH key file %q: %v", keyPath, err)
		}
		keys = append(keys, p)
	}

	var signers []ssh.Signer
	for _, p := range keys {
		signer, err := ssh.ParsePrivateKey(p)
		if err != nil {
			return nil, err
		}
		signers = append(signers, signer)
	}
	return signers, nil
}
