package emote

import (
	"strings"
	"unicode"
)

// Emote is the information Kaiyan needs about an emote.
type Emote struct {
	// ID is the emote ID per the source.
	ID string `json:"id"`
	// Name is the text of the emote as would be parsed from message text.
	Name string `json:"name"`
	// Source is the name of the emote source, e.g. "7TV", "Twitch:cirno_tv", &c.
	Source string `json:"source"`
	// Link is a hyperlink to manage the emote.
	Link string `json:"link"`
	// Image is a hyperlink to the emote image of any size.
	Image string `json:"image"`
}

// Parser finds emotes in a message.
//
// Parser assumes that emotes are bound by whitespace.
type Parser struct {
	m map[string]Emote
	// TODO(branden): more efficient data structure; trie?
}

// NewParser creates a Parser for the given list of emotes.
func NewParser(emotes ...Emote) Parser {
	m := make(map[string]Emote, len(emotes))
	for _, e := range emotes {
		m[e.Name] = e
	}
	return Parser{m}
}

// Next parses the next emote instance from the message and returns the
// remainder of the message text following it.
// If there is no emote in the message the returned emote has an empty ID.
func (p Parser) Next(text string) (emote Emote, following string) {
	for text != "" {
		// First trim any existing space.
		text = strings.TrimSpace(text)
		// Then look for the next space.
		// If there is none, this is the last word of the message; we still
		// need to look it up.
		k := strings.IndexFunc(text, unicode.IsSpace)
		word := text
		if k >= 0 {
			word = text[:k]
			following = text[k:]
		} else {
			following = ""
		}
		em := p.m[word]
		if em.ID != "" {
			return em, following
		}
		text = following
	}
	// No emote found.
	return Emote{}, ""
}