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.
//
// AppJanitor can quarantine files, so guided mode deliberately runs the
// LOOKING half only: it lists candidates and stops. Nothing is moved, nothing
// is removed, and this file offers no way to ask for that.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  AppJanitor")
	fmt.Println("  Finds the leftover junk that quietly fills up a folder.")
	fmt.Println()
	fmt.Println("  Point it at a folder and it lists temporary files, editor backups,")
	fmt.Println("  stray log files, thumbnail caches and folders with nothing left in")
	fmt.Println("  them — telling you why each one was flagged and how much space it")
	fmt.Println("  is taking up.")
	fmt.Println()
	fmt.Println("  This is a look, not a clean-up. Nothing is moved, changed or")
	fmt.Println("  deleted here.")
	fmt.Println()

	suggested := suggestedFolder()
	for {
		fmt.Println("  Which folder shall I look through?")
		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 look through. 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("  Looking. On a large folder this can take a minute.")
		fmt.Println()
		guidedScan(answer)
		break
	}

	fmt.Println()
	fmt.Println("  Done — and nothing was touched. If you want AppJanitor to move")
	fmt.Println("  what it found into a quarantine folder, that is a command-line")
	fmt.Println("  job on purpose: appjanitor --help")
	pause(in)
}

// guidedScan runs the same read-only search the scan command runs, with the
// default junk patterns and empty-directory reporting turned on. It talks to
// findCandidates directly rather than to runScan so that a walk error prints a
// friendly line instead of calling os.Exit and slamming the window shut.
func guidedScan(dir string) {
	patterns := splitPatterns(defaultPatterns)
	fileCandidates, dirCandidates, err := findCandidates(dir, patterns, 0, false, true)
	if err != nil {
		fmt.Printf("  I could not finish looking through %s: %v\n", dir, err)
		return
	}

	fmt.Printf("  Looked through %s\n", dir)
	fmt.Println()
	if len(fileCandidates) == 0 && len(dirCandidates) == 0 {
		fmt.Println("  Nothing worth clearing out. That folder is tidy.")
		return
	}
	total := printCandidates(fileCandidates, dirCandidates)
	printSummary(fileCandidates, dirCandidates, total)
}

// suggestedFolder offers somewhere worth looking 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 ""
	}
	// Downloads is where leftovers pile up fastest, and Documents is the next
	// most likely place somebody wants tidied.
	for _, name := range []string{"Downloads", "Documents"} {
		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()
}
