package terminal

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"strings"
	"time"
)

func AskForConfirmation(message string) (bool, error) {
	reader := bufio.NewReader(os.Stdin)
	for {
		fmt.Printf("%s [y/n]: ", message)

		response, err := reader.ReadString('\n')
		if err != nil {
			return false, err
		}

		response = strings.ToLower(strings.TrimSpace(response))

		if response == "y" || response == "yes" {
			return true, nil
		} else if response == "n" || response == "no" {
			return false, nil
		}
	}
}

func AskForInput(message string) (string, error) {
	reader := bufio.NewReader(os.Stdin)

	fmt.Printf(fmt.Sprintf("%s:", message))
	response, err := reader.ReadString('\n')

	if err != nil {
		return "", fmt.Errorf("couldn't read from command line: %v", err)
	}

	return strings.TrimSpace(response), nil
}

func WaitForCondition(conditionText string, timeout time.Duration, period time.Duration, conditionCheck func() (bool, error)) error {
	startTime := time.Now()
	endTime := startTime.Add(timeout)
	nextTime := startTime

	for time.Now().Before(endTime) {
		done, err := conditionCheck()
		if err != nil {
			return err
		}
		if done {
			return nil
		}

		fmt.Printf("Waiting on %s (%s)...\n", conditionText, durationText(time.Now().Sub(startTime)))

		now := time.Now()
		for now.After(nextTime) {
			nextTime = nextTime.Add(period)
		}

		time.Sleep(nextTime.Sub(now))
	}

	return fmt.Errorf("timed out waiting on %s after %s", conditionText, durationText(timeout))
}

func durationText(duration time.Duration) string {
	hours := int(math.Floor(duration.Hours()))
	minutes := int(math.Floor(duration.Minutes())) % 60
	seconds := int(math.Floor(duration.Seconds())) % 60

	text := ""
	if hours > 0 {
		text += fmt.Sprintf("%d hours ", hours)
	}
	if minutes > 0 {
		text += fmt.Sprintf("%d minutes ", minutes)
	}
	if seconds > 0 {
		text += fmt.Sprintf("%d seconds ", seconds)
	}

	if len(text) == 0 {
		text = "0 seconds"
	}

	return strings.TrimSpace(text)
}
