package main

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

// runGuided is what happens when somebody double-clicks CopySure instead of
// typing its name at a prompt.
//
// Explorer opens a console, runs the program with no arguments, and destroys
// the window the instant the process exits — so printing usage and quitting
// looks exactly like a crash. When we know we were double-clicked we ask the
// two things CopySure needs and stay on screen until the reader is done.
//
// The guided session only ever COMPARES. Copying is left to the command line:
// nothing here writes, moves or overwrites a single file.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  CopySure")
	fmt.Println("  Check that a copy really arrived intact.")
	fmt.Println()
	fmt.Println("  Give it the folder you copied FROM and the folder you copied TO.")
	fmt.Println("  It reads every file in both, compares them by their true content,")
	fmt.Println("  and tells you what is missing, what is extra and what does not match.")
	fmt.Println()
	fmt.Println("  This comparison only reads. Nothing is copied, changed or deleted.")
	fmt.Println()

	source, ok := askFolder(in, "Which folder is the ORIGINAL?", suggestedFolder())
	if !ok {
		return
	}
	fmt.Println()
	destination, ok := askFolder(in, "And which folder is the COPY you want checked?", "")
	if !ok {
		return
	}

	fmt.Println()
	fmt.Println("  Comparing. Every file is read right through, so a big folder")
	fmt.Println("  takes a while.")
	fmt.Println()
	diffTrees(source, destination)

	fmt.Println()
	fmt.Println("  Done. Anything listed above is a real difference between the two")
	fmt.Println("  folders, not a guess from names or dates.")
	fmt.Println("  There is a command-line version too, which can also make the copy")
	fmt.Println("  for you and verify it as it goes: copysure --help")
	pause(in)
}

// askFolder puts one question, accepts a default with a single keypress, and
// keeps asking until the answer is a folder that really exists. It returns
// false only when stdin closes, which means there is nobody left to ask.
func askFolder(in *bufio.Scanner, question, suggested string) (string, bool) {
	for {
		fmt.Printf("  %s\n", question)
		if suggested != "" {
			fmt.Printf("  (press Enter for %s)\n", suggested)
		}
		fmt.Println("  Tip: you can drag a folder from Explorer onto this window to")
		fmt.Println("  paste its location, then press Enter.")
		fmt.Print("  > ")

		if !in.Scan() {
			return "", false
		}
		answer := strings.TrimSpace(in.Text())
		answer = strings.Trim(answer, `"`)
		if answer == "" {
			answer = suggested
		}
		if answer == "" {
			fmt.Println()
			fmt.Println("  I need a folder for that. 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()
			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
	}
}

// suggestedFolder offers somewhere worth looking that is certain to exist, so
// the reader can get going with one keypress.
func suggestedFolder() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ""
	}
	// The folders people actually copy off to a backup drive.
	for _, name := range []string{"Documents", "Pictures"} {
		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()
}
