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.
//
// The guided session reads the list and reports on it. It does not download:
// starting a long batch transfer, at whatever speed, against somebody else's
// server is not something to begin because a window was double-clicked, and
// the rate limit is the whole reason this tool exists. Downloading stays on 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("  DropDeck")
	fmt.Println("  Check a download list before you set it going.")
	fmt.Println()
	fmt.Println("  You keep the addresses you want in a plain text file, one per")
	fmt.Println("  line. Show it that file and it counts what is in there, groups")
	fmt.Println("  the addresses by which site they come from, and points out any")
	fmt.Println("  line it cannot use.")
	fmt.Println()
	fmt.Println("  It only reads your list. Nothing is downloaded and nothing is")
	fmt.Println("  written.")
	fmt.Println()

	suggested := suggestedManifest()
	for {
		fmt.Println("  Where is your 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 == "" {
			fmt.Println()
			fmt.Println("  I need a text file with one web address per line.")
			fmt.Println("  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 the file, or the folder holding it, from")
			fmt.Println("  Explorer onto this window to paste its location, then press")
			fmt.Println("  Enter.")
			fmt.Println()
			continue
		case info.IsDir():
			fmt.Println()
			fmt.Printf("  %q is a folder. I need the list file inside it.\n", answer)
			fmt.Println()
			continue
		}

		fmt.Println()
		cmdPlan([]string{answer})
		break
	}

	fmt.Println()
	fmt.Println("  Done. Nothing was downloaded — that was a look at the list only.")
	fmt.Println("  The command-line version is the one that fetches, and it can hold")
	fmt.Println("  itself to a speed limit while it does: dropdeck --help")
	pause(in)
}

// suggestedManifest offers a list file the reader can accept with one keypress,
// but only when one is really there: offering a name that does not exist would
// send the very first keypress straight into an error.
func suggestedManifest() 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, filepath.Join(home, "Downloads"), home)
	}
	for _, dir := range dirs {
		for _, name := range []string{"manifest.txt", "urls.txt", "downloads.txt", "playlist.txt"} {
			candidate := filepath.Join(dir, name)
			if info, err := os.Stat(candidate); err == nil && !info.IsDir() {
				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()
}
