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.
//
// LocalLens can write one thing: the index file that "index" builds. The
// guided session does not build one, so it writes nothing. It reads the
// indexes the team has already shared, reports on them, and returns — one
// pass, no loop, nothing left running.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  LocalLens")
	fmt.Println("  See what your team has, across everybody's machines at once.")
	fmt.Println()
	fmt.Println("  Each person runs LocalLens on their own machine, which writes one")
	fmt.Println("  small index file, and everybody copies those files into a shared")
	fmt.Println("  folder. Point this at that folder and it tells you whose index is")
	fmt.Println("  there, how old each one is, and which files exist on more than one")
	fmt.Println("  machine.")
	fmt.Println()
	fmt.Println("  It only reads. Nothing is moved, changed or deleted, and no index")
	fmt.Println("  file is written.")
	fmt.Println()

	suggested := suggestedFolder()
	for {
		fmt.Println("  Which folder holds the shared index files?")
		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 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
		}

		if !hasUsableIndexes(answer) {
			fmt.Println()
			fmt.Printf("  I could not find a usable LocalLens index in %s.\n", answer)
			fmt.Println()
			fmt.Println("  An index is made on each machine first, with a command like:")
			fmt.Println("    locallens index <your documents folder> --out alpha.json --machine alpha")
			fmt.Println()
			fmt.Println("  Copy each machine's file into one shared folder, then point me at")
			fmt.Println("  that folder. Try another folder, or close this window.")
			fmt.Println()
			continue
		}

		fmt.Println()
		fmt.Println("  Reading the indexes.")
		fmt.Println()
		reportOnIndexes(answer)
		break
	}

	fmt.Println()
	fmt.Println("  An index describes a machine as it was when it was built, so check")
	fmt.Println("  the dates above before treating any of this as today's truth.")
	fmt.Println()
	fmt.Println("  The command-line version searches all of these at once by word, and")
	fmt.Println("  marks which machines hold a copy of each hit: locallens help")
	pause(in)
}

// hasUsableIndexes checks the folder before either command runs. Both of them
// exit the process when they find nothing to load, and an exit here would
// close the window before the reader had read a word of the explanation.
func hasUsableIndexes(dir string) bool {
	paths, err := collectIndexPaths(nil, dir)
	if err != nil || len(paths) == 0 {
		return false
	}
	loaded, _ := loadIndexes(paths)
	return len(loaded) > 0
}

// reportOnIndexes runs the two read-only reports that make sense without a
// search term: who is in the shared folder, and what is duplicated across
// them.
func reportOnIndexes(dir string) {
	cmdMachines([]string{"--dir", dir})
	fmt.Println()
	cmdDuplicates([]string{"--dir", dir})
}

// suggestedFolder offers a folder that is certain to exist, so the prompt can
// be answered with one keypress even before a shared folder has been agreed.
func suggestedFolder() string {
	home, err := os.UserHomeDir()
	if err != nil {
		return ""
	}
	// The names teams most often give the folder they sync indexes into.
	for _, name := range []string{"share", "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()
}
