//go:build windows
// +build windows

// Note the terminal manipulation functions herein are mostly stubs. They
// don't really do anything and the xs demo client depends on a wrapper
// script using the 'stty' tool to actually set the proper mode for
// password login and raw mode required, then restoring it upon logout/exit.
//
// mintty uses named pipes and ptys rather than Windows 'console'
// mode, and Go's x/crypto/ssh/terminal libs only work for the latter, so
// until some truly cross-platform terminal mode handling makes it into the
// go std lib I'm not going to jump through hoops trying to be cross-platform
// here; the wrapper does the bare minimum to make the client workable
// under MSYS+mintty which is what I use.

package xs

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"os/exec"
	"os/signal"
)

type State struct {
}

// MakeRaw put the terminal connected to the given file descriptor into raw
// mode and returns the previous state of the terminal so that it can be
// restored.
func MakeRaw(f *os.File) (*State, error) {
	cmd := exec.Command("stty", "-echo", "raw")
	cmd.Stdin = f
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
		return &State{}, err
	}

	// MSYS2/CYGWIN: wintty needs CTRL-C caught
	// ----------------------------------------
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt, os.Kill)
	go func() {
		for sig := range c {
			_ = sig
			//fmt.Println(sig)
		}
	}()
	// ----------------------------------------

	return &State{}, nil
}

// GetState returns the current state of a terminal which may be useful to
// restore the terminal after a signal.
func GetState(f *os.File) (*State, error) {
	return &State{}, nil
}

// Restore restores the terminal connected to the given file descriptor to a
// previous state.
func Restore(f *os.File, state *State) error {
	cmd := exec.Command("stty", "sane")
	cmd.Stdin = f
	err := cmd.Run()
	if err != nil {
		log.Fatal(err)
		return nil
	}
	return nil
}

// ReadPassword reads a line of input from a terminal without local echo.  This
// is commonly used for inputting passwords and other sensitive data. The slice
// returned does not include the \n.
func ReadPassword(f *os.File) (pw []byte, err error) {
	sttycmd, err := exec.LookPath("stty")
	if err != nil {
		return nil, err
	} else {
		//fmt.Printf("stty found at: %v\n", sttycmd)
		cmdOff := exec.Command(sttycmd, "-echo")
		cmdOff.Stdin = f    //os.Stdin
		cmdOff.Stdout = nil //os.Stdout
		cmdOff.Stderr = nil //os.Stderr
		err = cmdOff.Run()
		if err != nil {
			return nil, err
		}

		//fmt.Printf("Enter password:")
		scanner := bufio.NewScanner(os.Stdin)
		scanner.Scan()
		err = scanner.Err()
		if err != nil {
			return nil, err
		}
		pw = scanner.Bytes()
		fmt.Println()
		cmdOn := exec.Command(sttycmd, "echo")
		cmdOn.Stdin = f    //os.Stdin
		cmdOn.Stdout = nil //os.Stdout
		cmdOn.Stderr = nil //os.Stderr
		err = cmdOn.Run()
		if err != nil {
			return nil, err
		}
	}
	return
}
