package ugh

import (
	"regexp"
	"strings"
)

// Matcher describes what to wait for on screen. Implement this interface
// to create custom matchers for use with Console.Expect.
type Matcher interface {
	Match(screen string) bool
	String() string
}

type substringMatcher string

func (m substringMatcher) Match(screen string) bool {
	return strings.Contains(screen, string(m))
}

func (m substringMatcher) String() string {
	return string(m)
}

type regexpMatcher struct {
	pattern *regexp.Regexp
}

func (m *regexpMatcher) Match(screen string) bool {
	return m.pattern.MatchString(screen)
}

func (m *regexpMatcher) String() string {
	return m.pattern.String()
}

type matchScreenFunc struct {
	fn   func(string) bool
	desc string
}

func (m matchScreenFunc) Match(screen string) bool {
	return m.fn(screen)
}

func (m matchScreenFunc) String() string {
	return m.desc
}

// MatchScreen creates a Matcher from a description and a predicate function.
func MatchScreen(desc string, fn func(screen string) bool) Matcher {
	return matchScreenFunc{fn: fn, desc: desc}
}

// String creates a Matcher that waits for the screen to contain s.
func String(s string) Matcher { return substringMatcher(s) }

// Regexp creates a Matcher that waits for the screen to match the regexp pattern.
func Regexp(pattern string) Matcher { return &regexpMatcher{regexp.MustCompile(pattern)} }

// Confirm creates a substring Matcher for a huh Confirm field title.
func Confirm(title string) Matcher { return substringMatcher(title) }

// ConfirmRegexp creates a regexp Matcher for a huh Confirm field title.
func ConfirmRegexp(pattern string) Matcher { return &regexpMatcher{regexp.MustCompile(pattern)} }

// Select creates a substring Matcher for a huh Select field title.
func Select(title string) Matcher { return substringMatcher(title) }

// SelectRegexp creates a regexp Matcher for a huh Select field title.
func SelectRegexp(pattern string) Matcher { return &regexpMatcher{regexp.MustCompile(pattern)} }

// MultiSelect creates a substring Matcher for a huh MultiSelect field title.
func MultiSelect(title string) Matcher { return substringMatcher(title) }

// Input creates a substring Matcher for a huh Input field title.
func Input(title string) Matcher { return substringMatcher(title) }

// Text creates a substring Matcher for a huh Text field title.
func Text(title string) Matcher { return substringMatcher(title) }

// Note creates a substring Matcher for a huh Note field title.
func Note(title string) Matcher { return substringMatcher(title) }
