package main

import (
	"bufio"
	"fmt"
	"os"
	"path/filepath"
	"strings"
)

// 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 one
// question the program actually needs and stay on screen until the reader is
// done.
//
// 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.
//
// HardwareLens only ever reads, so the report card itself is the safe action.
// The guided session runs it without an output file, so the one file
// HardwareLens is capable of writing is not written either.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  HardwareLens")
	fmt.Println("  A one-page report card for the computer in front of you.")
	fmt.Println()
	fmt.Println("  It writes down what this machine is, times how fast it can work")
	fmt.Println("  right now, and finishes with plain-English remarks about anything")
	fmt.Println("  that looks worth knowing. Read it, or hand it to whoever is helping")
	fmt.Println("  you.")
	fmt.Println()
	fmt.Println("  It only reads. Nothing is moved, changed or deleted.")
	fmt.Println()

	suggested := suggestedFolder()
	watch := ""
	for {
		fmt.Println("  Is there a folder you would like included in the report?")
		fmt.Println("  (it will be measured: size, file count, biggest file)")
		if suggested != "" {
			fmt.Printf("  (press Enter for %s, or type none to skip)\n", suggested)
		} else {
			fmt.Println("  (press Enter to skip)")
		}
		fmt.Print("  > ")

		if !in.Scan() {
			// stdin closed on us; there is nothing sensible left to ask.
			return
		}
		answer := strings.TrimSpace(in.Text())
		answer = strings.Trim(answer, `"`)
		if answer == "" {
			answer = suggested
		}
		if answer == "" || strings.EqualFold(answer, "none") || strings.EqualFold(answer, "no") {
			break
		}

		info, err := os.Stat(answer)
		switch {
		case err != nil:
			fmt.Println()
			fmt.Printf("  I cannot find %q.\n", answer)
			fmt.Println("  Tip: you can drag a folder from Explorer onto this window to")
			fmt.Println("  paste its location, then press Enter. Or type none to skip.")
			fmt.Println()
			continue
		case !info.IsDir():
			fmt.Println()
			fmt.Printf("  %q is a file, not a folder. Give me the folder it sits in,\n", answer)
			fmt.Println("  or type none to skip this part.")
			fmt.Println()
			continue
		}
		watch = answer
		break
	}

	fmt.Println()
	fmt.Println("  Measuring. The speed check takes about half a second.")
	fmt.Println()

	// The report card, printed and not saved: no output file is requested, so
	// the only file this program can write is not written.
	if watch == "" {
		cmdReport(nil)
	} else {
		cmdReport([]string{"--watch", watch})
	}

	fmt.Println()
	fmt.Println("  Read the \"WHAT THIS TOOL CANNOT SEE\" list above before treating a")
	fmt.Println("  missing measurement as a clean bill of health.")
	fmt.Println()
	fmt.Println("  The command-line version can save this to a file to send on, and")
	fmt.Println("  can measure several folders at once: hardwarelens --help")
	pause(in)
}

// suggestedFolder offers somewhere worth measuring that is certain to exist,
// so the reader can get a useful answer by pressing one key.
func suggestedFolder() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ""
	}
	for _, name := range []string{"Documents", "Downloads"} {
		candidate := filepath.Join(home, name)
		if info, err := os.Stat(candidate); err == nil && info.IsDir() {
			return candidate
		}
	}
	return home
}

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