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.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  StorageLens")
	fmt.Println("  See how much room a location is using before it runs out.")
	fmt.Println()
	fmt.Println("  Give it one or more folders — a shared drive, a backup location, a")
	fmt.Println("  department's files — and it adds up the size and the number of files")
	fmt.Println("  in each, ranks them biggest first, and names the largest files.")
	fmt.Println()
	fmt.Println("  It only reads. Nothing is deleted, moved or changed.")
	fmt.Println()

	suggested := suggestedFolder()
	var targets []string
	for {
		if len(targets) == 0 {
			fmt.Println("  Which folder shall I measure?")
			if suggested != "" {
				fmt.Printf("  (press Enter for %s)\n", suggested)
			}
		} else {
			fmt.Printf("  Another folder to add? (%d so far — press Enter to start)\n", len(targets))
		}
		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 == "" {
			if len(targets) > 0 {
				break
			}
			answer = suggested
		}
		if answer == "" {
			fmt.Println()
			fmt.Println("  I need a folder to measure. Try again, or close this window.")
			fmt.Println()
			continue
		}

		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.")
			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()
			continue
		}

		targets = append(targets, answer)
		fmt.Printf("  Added %s\n", answer)
		fmt.Println()
	}

	fmt.Println()
	fmt.Println("  Working. On a large location this can take a minute.")
	fmt.Println()
	runAudit(targets)

	fmt.Println()
	fmt.Println("  Done. Run it again any time on other folders.")
	fmt.Println("  There is a command-line version too: storagelens 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 ""
	}
	// A home directory is the honest default, but the folders that quietly
	// grow into a capacity problem are the ones worth offering first.
	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()
}
