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 thing
// the program needs and stay on screen until the reader is done.
//
// RestoreGuard can copy files into a vault and it can delete whole snapshots
// out of one, so the guided session only ever READS the vault: it lists what
// is in there and then shows the retention plan as a preview. It removes
// nothing and writes nothing. Actually thinning a vault stays a deliberate act
// at the command line.
//
// 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("  RestoreGuard")
	fmt.Println("  Look inside a backup vault and see what it is keeping.")
	fmt.Println()
	fmt.Println("  RestoreGuard stores dated snapshots of a folder and thins them out as")
	fmt.Println("  they age: everything from the last day, then one a day for a week, then")
	fmt.Println("  one a week for a month. Recent history stays detailed, old history")
	fmt.Println("  stays small.")
	fmt.Println()
	fmt.Println("  This window reads your vault and shows both halves of that: what is in")
	fmt.Println("  there now, and what the next tidy-up would keep or drop. It is a look,")
	fmt.Println("  not a change — nothing is written or removed while you are in here.")
	fmt.Println()

	vault, ok := askVault(in, suggestedVault())
	if !ok {
		return
	}

	fmt.Println()
	fmt.Println("  ---- what is in the vault ----")
	fmt.Println()
	cmdList([]string{vault})

	fmt.Println()
	fmt.Println("  ---- what the next tidy-up would decide ----")
	fmt.Println()
	cmdPrune([]string{vault})

	fmt.Println()
	fmt.Println("  Nothing was changed or removed.")
	fmt.Println("  To take a new snapshot, or to actually carry out that tidy-up, run")
	fmt.Println("  RestoreGuard from a command prompt: restoreguard help lists everything.")
	pause(in)
}

// askVault asks for the vault folder and keeps asking until it gets one that
// really exists. A folder with no snapshots in it is fine — the report says so
// in plain words, which is a more useful answer than a refusal.
func askVault(in *bufio.Scanner, suggested string) (string, bool) {
	for {
		fmt.Println("  Which folder is your backup vault?")
		fmt.Println("  It is the folder RestoreGuard writes its snapshots into, often on")
		fmt.Println("  an external disk.")
		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 "", false
		}
		answer := strings.Trim(strings.TrimSpace(in.Text()), `"`)
		if answer == "" {
			answer = suggested
		}
		if answer == "" {
			fmt.Println()
			fmt.Println("  I need a folder to look in. 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
		}
		return answer, true
	}
}

// suggestedVault offers a starting point the reader can accept with one
// keypress. It only ever returns somewhere that exists, so pressing Enter can
// never greet them with an error.
func suggestedVault() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ""
	}
	for _, name := range []string{"RestoreGuard", "Backups", "Backup"} {
		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()
}
