// 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"
	"strconv"
	"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 = 1 * time.Minute
)

// 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
	Host string `json:"host"`

	// 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"`

	// PDUIp is the IP address of the pdu
	PDUIp string `json:"pduIp"`

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

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 SSH to reboot.")
		rebooter = NewSSHRebooter(nodename, signers)
	} else {
		log.Printf("Using serial to reboot.")
		rebooter = NewSerialRebooter(serial)
	}
	return rebooter.reboot()
}

// Powercycle the device using an out of band method
func (c PowerClient) Powercycle(nodename, mac string, serial io.ReadWriter, signers []ssh.Signer) 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, mac); 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")
		port, err := strconv.Atoi(c.PDUPort)
		if err != nil {
			return err
		}
		if err := PDUReboot(port, c.PDUIp, c.Username, c.Password); err != nil {
			return err
		}
	case "ACTS_PDU":
		port, err := strconv.Atoi(c.PDUPort)
		if err != nil {
			return err
		}
		conn := NewActsPDUConn(c.PDUIp, c.Username, c.Password)
		if err := conn.Reboot(port); err != nil {
			return err
		}
		// TODO(rudymathu): Remove this dependency on ssh when all connectivity testbeds have
		// serial connections.
		if serial == nil {
			log.Printf("Powercycle complete; using ssh to send dm reboot recovery.")
			time.Sleep(powercycleWait)
			rebooter := NewSSHRebooter(nodename, signers)
			return rebooter.reboot()
		}
	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()
}

// PowercycleIntoFastboot powercycles an Astro or Sherlock into fastboot.
func (c PowerClient) PowercycleIntoFastboot(nodename string, mac string, serial io.ReadWriter) error {
	if c.Type != "PDU" {
		return errors.New("fastboot not supported for device")
	}
	if serial == nil {
		return errors.New("PDU Reboot requires serial connection.")
	}
	log.Printf("Using PDU to powercycle")
	port, err := strconv.Atoi(c.PDUPort)
	if err != nil {
		return err
	}
	if err := PDUReboot(port, c.PDUIp, c.Username, c.Password); err != nil {
		return err
	}

	// Spam the serial line to get into fastboot mode.
	// We spam the line so much because it gives us the greatest chance of entering fastboot.
	for i := 1; i < 15000; i++ {
		if _, err := io.WriteString(serial, "\nf\n"); err != nil {
			return err
		}
		time.Sleep(1 * time.Millisecond)
	}
	time.Sleep(1 * time.Second)
	// This serial command instructs Sherlocks to enter fastboot mode.
	if _, err := io.WriteString(serial, "\nfastboot 0\n"); err != nil {
		return err
	}
	return nil
}

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.ConnectToNodeDeprecated(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`
	err = session.Start("dm reboot-recovery")
	if err != nil {
		return err
	}

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

	select {
	case err := <-done:
		return err
	case <-time.After(10 * time.Second):
		return nil
	}
}
