//+lbuild experiment

// ! EXPERIMENTAL
package main

import (
    "errors"
    "regexp"
)

type Mango struct {
    tagFinder *regexp.Regexp
}

func (m *Mango) Init() {
    m.tagFinder = regexp.MustCompile(`(?s)\{\{(.*)\}\}`)
}

func (m *Mango) Parse(tmpl string) (out string, err error) {
    tagIndices := m.tagFinder.FindAllStringIndex(tmpl, -1)
    if len(tagIndices) > 0 {
        if tagIndices[0][0] == 0 {
            return "", errors.New("We don't support tags in the outermost layer yet")
        }
        var lastTag = 0
        var lastID = 0
        for _, tagIndex := range tagIndices {
            var nestingLayer = 0
            for i := tagIndex[0]; i > 0; i-- {
                switch tmpl[i] {
                case '>':
                    ii, closeTag, err := m.tasteTagToLeft(tmpl, i)
                    if err != nil {
                        return "", err
                    }
                    if closeTag {
                        nestingLayer++
                    } else {
                        _, tagID := m.parseTag(tmpl, ii, i)
                        if tagID == "" {
                            out += tmpl[lastTag:ii] + m.injectID(ii, i)
                            lastID++
                        } else {
                            out += tmpl[lastTag:i]
                        }
                    }
                case '<':

                }
            }
        }
    }
    return "", nil
}

func (m *Mango) injectID(start int, end int) string {
    return ""
}

func (m *Mango) parseTag(tmpl string, start int, end int) (tagType string, tagID string) {
    var i = start
    for ; i < end; i++ {
        if tmpl[i] == ' ' {
            break
        }
    }
    tagType = tmpl[start:i]
    i = start
    for ; i < (end - 4); i++ {
        if tmpl[i] == ' ' && tmpl[i+1] == 'i' && tmpl[i+2] == 'd' && tmpl[i+3] == '=' {
            tagID = m.extractAttributeContents(tmpl, i+4, end)
        }
    }
    return tagType, tagID
}

func (m *Mango) extractAttributeContents(tmpl string, i int, end int) (contents string) {
    var start = i
    var quoteChar byte = 0 // nolint
    if m.isHTMLQuoteChar(tmpl[i]) {
        i++
        quoteChar = tmpl[i]
    }
    i += 3
    for ; i < end; i++ {
        if quoteChar != 0 {
            if tmpl[i] == quoteChar {
                break
            }
        } else if tmpl[i] == ' ' {
            break
        }
    }
    return tmpl[start:i]
}

func (m *Mango) isHTMLQuoteChar(char byte) bool {
    return char == '\'' || char == '"'
}

func (m *Mango) tasteTagToLeft(tmpl string, index int) (indexOut int, closeTag bool, err error) {
    var foundLeftBrace = false
    for ; index > 0; index-- {
        // What if the / isn't adjacent to the < but has a space instead? Is that even valid?
        if index >= 1 && tmpl[index] == '/' && tmpl[index-1] == '<' {
            closeTag = true
            break
        } else if tmpl[index] == '<' {
            foundLeftBrace = true
        }
    }
    if !foundLeftBrace {
        return index, closeTag, errors.New("The left portion of the tag is missing")
    }
    return index, closeTag, nil
}