package main

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

// 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.
//
// FreshDesk never deletes anything, so there is no dangerous action to avoid
// here. The guided session goes one step further than the survey command and
// writes no report file either: it measures, prints the table, and stops.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  FreshDesk")
	fmt.Println("  Measure how much space on this machine could be reclaimed.")
	fmt.Println()
	fmt.Println("  Point it at a folder and it adds up the temporary files, caches,")
	fmt.Println("  logs, crash reports, leftover installers and empty folders inside,")
	fmt.Println("  and tells you how old the oldest and newest of each are.")
	fmt.Println()
	fmt.Println("  It only measures. Nothing is deleted, moved or changed — FreshDesk")
	fmt.Println("  has no code that removes a file at all.")
	fmt.Println()

	suggested := suggestedFolder()
	for {
		fmt.Println("  Which folder shall I measure?")
		if suggested != "" {
			fmt.Printf("  (press Enter for %s)\n", suggested)
		}
		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 == "" {
			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
		}

		fmt.Println()
		fmt.Println("  Measuring. On a large folder this can take a minute.")
		fmt.Println()
		surveyOneFolder(answer)
		break
	}

	fmt.Println()
	fmt.Println("  Read that total as \"at least this much\": FreshDesk counts the")
	fmt.Println("  categories it knows about, and applications invent new ones.")
	fmt.Println()
	fmt.Println("  The command-line version saves this as a report file, and merges the")
	fmt.Println("  reports from a whole fleet into one picture: freshdesk --help")
	pause(in)
}

// surveyOneFolder runs the measuring half of the survey command over one root,
// across every category, and prints the same table survey prints. Passing an
// empty output path is what keeps this session from writing a report file: the
// report exists only in memory and is printed.
func surveyOneFolder(dir string) {
	machine, err := os.Hostname()
	if err != nil || strings.TrimSpace(machine) == "" {
		machine = "this-computer"
	}

	rep := surveyRoots(machine, []string{dir}, catalog, time.Now())
	printSurvey(os.Stdout, rep, "")
}

// 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 ""
	}
	// On Windows this is where caches, logs and crash dumps actually
	// accumulate; elsewhere the home directory is the honest default.
	for _, name := range []string{"AppData", "Library"} {
		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()
}
