package main

import (
	"bufio"
	"fmt"
	"os"
	"strings"
)

// defaultGuidedServer is the address offered to somebody who double-clicked the
// program. A team server usually runs on another machine, but the person most
// likely to double-click this icon is sitting at the machine that runs it, so
// the local one is the answer worth offering for a single keypress.
const defaultGuidedServer = "http://localhost:8080"

// runGuided is what happens when somebody double-clicks the program instead of
// typing its name at a prompt.
//
// Without this, Explorer opens a console, main() finds no arguments, prints
// the usage text to stderr and exits — and Windows destroys the window in the
// same instant. From the other side of the screen that is indistinguishable
// from a crash. So when we know we were double-clicked, we ask the two
// questions the program actually needs and stay on screen until the reader is
// done.
//
// The guided session shows the queue. It does not add to it and it does not
// start the server: submitting puts a download on somebody else's machine, and
// serving blocks forever writing files into a shared folder. Neither is a
// reasonable thing to begin because an icon was double-clicked. Both stay on
// the command line.
//
// Reading the queue means asking the team server for it, which is a network
// call — unavoidably so, because a shared queue is the entire product and
// every read-only thing this tool does is a request to that server.
//
// This path is entered ONLY when there are no arguments and both ends of the
// program are a real console. Any scripted or piped use takes exactly the same
// code path it always did.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  FetchForge")
	fmt.Println("  See what your team's shared download queue is doing.")
	fmt.Println()
	fmt.Println("  One machine on your team holds the queue. Everybody adds to it")
	fmt.Println("  and everybody sees the same list. Give this the address of that")
	fmt.Println("  machine and it shows you every item: who asked for it, whether it")
	fmt.Println("  has finished, and how big it turned out to be.")
	fmt.Println()
	fmt.Println("  It only asks and reports. Nothing is added to the queue and")
	fmt.Println("  nothing is downloaded.")
	fmt.Println()

	for {
		server, ok := askServer(in)
		if !ok {
			return
		}
		token, ok := askToken(in)
		if !ok {
			return
		}

		fmt.Println()
		if err := cmdStatus([]string{"--server", server, "--token", token}); err != nil {
			fmt.Println()
			fmt.Printf("  That did not work: %v\n", err)
			fmt.Println()
			fmt.Println("  The usual reasons are that the server is not running yet, that")
			fmt.Println("  the address points somewhere else, or that the shared password")
			fmt.Println("  is not the one the server was started with.")
			fmt.Println("  Try again, or close this window.")
			fmt.Println()
			continue
		}
		break
	}

	fmt.Println()
	fmt.Println("  Done. That is the whole team's queue as it stands right now.")
	fmt.Println("  The command-line version is the one that adds to the queue and")
	fmt.Println("  the one that runs the server: fetchforge --help")
	pause(in)
}

// askServer asks where the team server is and hands the answer to the same
// client builder the command line uses, so a mistyped address is caught here
// with a sentence rather than half a second later as a request to nowhere.
func askServer(in *bufio.Scanner) (string, bool) {
	for {
		fmt.Println("  Which machine holds the queue?")
		fmt.Printf("  (press Enter for %s)\n", defaultGuidedServer)
		fmt.Print("  > ")

		if !in.Scan() {
			return "", false
		}
		answer := strings.TrimSpace(in.Text())
		answer = strings.Trim(answer, `"`)
		if answer == "" {
			answer = defaultGuidedServer
		}
		// The token is checked separately; a placeholder here keeps this to a
		// question about the address alone.
		if _, err := newClient(answer, "checking-the-address"); err != nil {
			fmt.Println()
			fmt.Printf("  I cannot make an address out of %q.\n", answer)
			fmt.Println("  It should look like buildbox:8080, or the whole thing:")
			fmt.Println("  http://buildbox:8080")
			fmt.Println()
			continue
		}
		return answer, true
	}
}

// askToken asks for the shared password. An empty one is refused by the client
// builder anyway, so it is caught here where the reader gets a plain sentence.
func askToken(in *bufio.Scanner) (string, bool) {
	for {
		fmt.Println()
		fmt.Println("  What is the shared password for it?")
		fmt.Println("  (the one whoever started the server chose)")
		fmt.Print("  > ")

		if !in.Scan() {
			return "", false
		}
		answer := strings.TrimSpace(in.Text())
		answer = strings.Trim(answer, `"`)
		if answer != "" {
			return answer, true
		}
		fmt.Println()
		fmt.Println("  The server will not answer without it. Try again, or close")
		fmt.Println("  this window.")
	}
}

// pause keeps the console window open. Explorer closes it the moment the
// process exits, so without this the reader never sees the output.
func pause(in *bufio.Scanner) {
	fmt.Println()
	fmt.Print("  Press Enter to close this window. ")
	in.Scan()
}
