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.
//
// Guided mode runs "status" and nothing else. It reads the queue file and
// prints it; it downloads nothing, writes nothing and touches no file on disk.
// Starting a run means writing files across the network, which is a decision
// somebody should make on purpose, so it stays on the command line.
func runGuided() {
	in := bufio.NewScanner(os.Stdin)

	fmt.Println()
	fmt.Println("  DownloadPilot")
	fmt.Println("  Keep track of a list of downloads, even across a restart.")
	fmt.Println()
	fmt.Println("  DownloadPilot keeps your list of downloads in one file — what is")
	fmt.Println("  waiting, what finished, and what failed and why. Show me that file")
	fmt.Println("  and I will tell you where everything stands.")
	fmt.Println()
	fmt.Println("  This only reads the list. Nothing is downloaded and no file is")
	fmt.Println("  written or changed.")
	fmt.Println()

	suggested := suggestedQueueFile()
	for {
		fmt.Println("  Where is your download list?")
		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 == "" {
			// Nothing typed and nothing to suggest: this reader has not made a
			// list yet. Say how, rather than asking the same question forever.
			explainHowToStart()
			break
		}

		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 the file — or the folder holding it — from")
			fmt.Println("  Explorer onto this window to paste its location.")
			fmt.Println()
			continue
		case info.IsDir():
			fmt.Println()
			fmt.Printf("  %q is a folder. I need the list file itself, which is\n", answer)
			fmt.Println("  usually something like queue.json inside it.")
			fmt.Println()
			continue
		}

		// status stops dead on a file it cannot understand. Read it here first
		// so a wrong file becomes a question instead of the end of the run.
		if _, err := loadQueue(answer, false); err != nil {
			fmt.Println()
			fmt.Printf("  %q is not a DownloadPilot list — I could not read it.\n", answer)
			fmt.Println("  A list is a .json file made by DownloadPilot itself.")
			fmt.Println()
			continue
		}

		fmt.Println()
		cmdStatus([]string{"--queue", answer})
		break
	}

	fmt.Println()
	fmt.Println("  Done. Nothing was downloaded — that was a look at the list.")
	fmt.Println("  The command-line version adds items and runs them:")
	fmt.Println("  downloadpilot help")
	pause(in)
}

// explainHowToStart is what a reader with no list at all needs to hear. It is
// the one case where the honest answer is not "try again".
func explainHowToStart() {
	fmt.Println()
	fmt.Println("  You do not have a download list yet, so there is nothing to show.")
	fmt.Println()
	fmt.Println("  A list is made one item at a time, from a command prompt:")
	fmt.Println()
	fmt.Println("    downloadpilot add --queue queue.json <address> --out <filename>")
	fmt.Println()
	fmt.Println("  Add as many as you like, then start them all with:")
	fmt.Println()
	fmt.Println("    downloadpilot run --queue queue.json")
}

// suggestedQueueFile offers a list the reader already has, so they can get an
// answer by pressing one key. There is no list every machine is guaranteed to
// own, so this returns nothing rather than something wrong; the prompt copes
// with an empty suggestion by asking for a path instead.
func suggestedQueueFile() string {
	var dirs []string
	if wd, err := os.Getwd(); err == nil {
		dirs = append(dirs, wd)
	}
	if home, err := os.UserHomeDir(); err == nil {
		dirs = append(dirs, home, filepath.Join(home, "Downloads"))
	}
	for _, dir := range dirs {
		for _, name := range []string{"queue.json", "downloads.json", "downloadpilot.json"} {
			candidate := filepath.Join(dir, name)
			if info, err := os.Stat(candidate); err == nil && info.Mode().IsRegular() {
				return candidate
			}
		}
	}
	return ""
}

// 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()
}
