package search

import "strings"

// Search represents a parsed search query with inclusions and exclusions.
type Search struct {
	Includes []string
	Excludes []string
}

// ParseSearchString parses a user search query and supports "quoted phrases" and -negations.
func ParseSearchString(input string) *Search {
	var result = new(Search)

	var (
		negate bool
		phrase bool
		buf    = []rune{}
		commit = func() {
			var text = strings.TrimSpace(string(buf))
			if len(text) == 0 {
				return
			}
			if negate {
				result.Excludes = append(result.Excludes, text)
				negate = false
			} else {
				result.Includes = append(result.Includes, text)
			}
			buf = []rune{}
		}
	)

	for _, char := range input {
		// Inside a quoted phrase?
		if phrase {
			if char == '"' {
				// End of quoted phrase.
				commit()
				phrase = false
				continue
			}
			buf = append(buf, char)
			continue
		}

		// Start a quoted phrase?
		if char == '"' {
			phrase = true
			continue
		}

		// Negation indicator?
		if len(buf) == 0 && char == '-' {
			negate = true
			continue
		}

		// End of a word?
		if char == ' ' {
			commit()
			continue
		}

		buf = append(buf, char)
	}

	// Last word?
	commit()

	return result
}
