package templating

import (
	"strings"
)

// matcher determines which template should be applied to a given metric
// based on a filter tree.
type matcher struct {
	root            *node
	defaultTemplate *Template
}

// newMatcher creates a new matcher.
func newMatcher(defaultTemplate *Template) *matcher {
	return &matcher{
		root:            &node{},
		defaultTemplate: defaultTemplate,
	}
}

func (m *matcher) addSpec(tmplt templateSpec) error {
	// Parse out the default tags specific to this template
	tags := map[string]string{}
	if tmplt.tagstring != "" {
		for _, kv := range strings.Split(tmplt.tagstring, ",") {
			parts := strings.Split(kv, "=")
			tags[parts[0]] = parts[1]
		}
	}

	tmpl, err := NewTemplate(tmplt.separator, tmplt.template, tags)
	if err != nil {
		return err
	}
	m.add(tmplt.filter, tmpl)
	return nil
}

// add inserts the template in the filter tree based the given filter
func (m *matcher) add(filter string, template *Template) {
	if filter == "" {
		m.defaultTemplate = template
		m.root.separator = template.separator
		return
	}
	m.root.insert(filter, template)
}

// match returns the template that matches the given measurement line.
// If no template matches, the default template is returned.
func (m *matcher) match(line string) *Template {
	tmpl := m.root.search(line)
	if tmpl != nil {
		return tmpl
	}
	return m.defaultTemplate
}