// Copyright 2018 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"
	"errors"
	"fmt"
	"io"
	"log"
	"time"

	"go.fuchsia.dev/fuchsia/tools/net/sshutil"
	"golang.org/x/crypto/ssh"
)

// TODO(IN-977) Clean this up per suggestions in go/fxr/251550

const (
	// Controller machines use 192.168.42.1/24 for swarming bots
	// This will broadcast to that entire subnet.
	botBroadcastAddr = "192.168.42.255:9"

	// Controller machines have multiple interfaces, currently
	// 'eno2' is used for swarming bots.
	botInterface = "eno2"

	// Duration to wait before sending dm reboot-recovery after powercycle
	powercycleWait = 10 * time.Second
)

// PowerClient represents a power management configuration for a particular device.
type PowerClient struct {
	// Type is the type of manager to use.
	Type string `json:"type"`

	// Host is the network hostname of the manager, e.g. fuchsia-tests-pdu-001.
	Host string `json:"host"`

	// HostHwAddr is the ethernet MAC address of the manager,  e.g. 10:10:10:10:10:10
	HostMACAddr string `json:"host_mac_addr"`

	// Username is the username used to log in to the manager.
	Username string `json:"username"`

	// Password is the password used to log in to the manager..
	Password string `json:"password"`

	// PDUPort is the port the PDU uses to connect to this device.
	PDUPort int `json:"pdu_port"`
}

type Rebooter interface {
	reboot() error
}

type SshRebooter struct {
	nodename string
	signers []ssh.Signer
}

type SerialRebooter struct {
	serial io.ReadWriter
}

// RebootDevice attempts to reboot the specified device into recovery, and
// additionally uses the given configuration to reboot the device if specified.
func (c PowerClient) RebootDevice(signers []ssh.Signer, nodename string, serial io.ReadWriter) error {
	var rebooter Rebooter
	log.Printf("Attempting to soft reboot device %s", nodename)
	if serial != nil {
		log.Printf("Using serial to reboot.")
		rebooter = NewSerialRebooter(serial)
	} else {
		log.Printf("Using SSH to reboot.")
		rebooter = NewSSHRebooter(nodename, signers)
	}
	return rebooter.reboot()
}

// Powercycle the device using an out of band method
func (c PowerClient) Powercycle(nodename string, serial io.ReadWriter) error {
	log.Printf("Attempting to powercycle device %s", nodename)
	switch c.Type {
		case "amt":
			log.Printf("Using AMT to powercycle.")
			return AMTReboot(c.Host, c.Username, c.Password)
		case "wol":
			if serial == nil {
				return errors.New(fmt.Sprintf("WOL Reboot requires serial connection."))
			}
			log.Printf("Using WOL to powercycle")
			if err := WOLReboot(botBroadcastAddr, botInterface, c.HostMACAddr); err != nil {
				return err
			}
		case "pdu":
			if serial == nil {
				return errors.New(fmt.Sprintf("PDU Reboot requires serial connection."))
			}
			log.Printf("Using PDU to powercycle")
			if err := PDUReboot(c.PDUPort, c.Host, c.Username, c.Password); err != nil {
				return err
			}
		default:
			return errors.New(fmt.Sprintf("%v does not have AMT, WOL, or PDU support. Cannot powercycle.", nodename))
	}
	// Send dm reboot-recovery to the device so that it always boots into zedboot.
	log.Printf("Powercycle complete; using serial to send dm reboot recovery.")
	time.Sleep(powercycleWait)
	rebooter := NewSerialRebooter(serial)
	return rebooter.reboot()
}

func NewSerialRebooter(serial io.ReadWriter) *SerialRebooter {
	return &SerialRebooter{
		serial: serial,
	}
}

func (s *SerialRebooter) reboot() error {
	_, err := io.WriteString(s.serial, "\ndm reboot-recovery\n")
	return err
}

func NewSSHRebooter(nodename string, signers []ssh.Signer) *SshRebooter {
	return &SshRebooter{
		nodename: nodename,
		signers: signers,
	}
}

func (s *SshRebooter) reboot() error {
	config, err := sshutil.DefaultSSHConfigFromSigners(s.signers...)
	if err != nil {
		return err
	}

	client, err := sshutil.ConnectToNode(context.Background(), s.nodename, config)
	if err != nil {
		return err
	}

	defer client.Close()

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

	defer session.Close()

	// Invoke `dm reboot-recovery` with a 2 second delay in the background, then exit the SSH shell.
	// This prevents the SSH connection from hanging waiting for `dm reboot-recovery` to return.
	err = session.Start("{ sleep 2; dm reboot-recovery; } >/dev/null & exit")
	if err != nil {
		return err
	}

	done := make(chan error)
	go func() {
		done <- session.Wait()
	}()

	select {
	case err := <-done:
		return err
	}
}
