// 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
)

// DeviceConfig contains the static properties of a target device.
type DeviceConfig struct {
	// 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"`
}

// CreateDevices 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
}

// 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 {
	config        DeviceConfig
	signers       []ssh.Signer
	serial        io.ReadWriteCloser
	BootserverCmd []string
}

// 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)
		}
	}
	return &DeviceTarget{
		config:        config,
		signers:       signers,
		serial:        s,
		BootserverCmd: append(bootserverCmdStub, config.Network.Nodename),
	}, nil
}

// 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
}

// 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.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
}
