package cmd

import (
	"git.noahlan.cn/northlan/ntools-go/stringn/ac"
	"strings"
)

type (
	CMD struct {
		IsCMD bool     // 是否CMD
		Arr   []string // 具体CMD  []string
	}
	Parser struct {
		ac         ac.AhoCorasick
		distinct   bool // 命令是否去重
		allKeyArr  []string
		keywordMap map[string]struct{}
	}
	ParserBuilder struct {
	}
)

func NewCMDParser(distinct bool, keys ...string) *Parser {
	p := &Parser{
		distinct:   distinct,
		keywordMap: make(map[string]struct{}),
		allKeyArr:  make([]string, 0, len(keys)),
	}
	for _, keyword := range keys {
		p.keywordMap[keyword] = struct{}{}
		p.allKeyArr = append(p.allKeyArr, keyword)
	}
	builder := ac.NewAhoCorasickBuilder(ac.Opts{
		AsciiCaseInsensitive: true,
		MatchOnlyWholeWords:  false,
		MatchKind:            ac.LeftMostLongestMatch,
		DFA:                  true,
	})
	p.ac = builder.Build(p.allKeyArr)
	return p
}

func (p *Parser) ParseTest(content string) []ac.Match {
	return p.ac.FindAll(content)
}

// SetDistinct 设置命令去重
func (p *Parser) SetDistinct(distinct bool) {
	p.distinct = distinct
}

// Parse 从弹幕内容解析命令
// distinct 是否去重
func (p *Parser) Parse(content string) *CMD {
	// 移除多余空格,小写
	tmpContent := strings.ToLower(strings.TrimSpace(content))

	allKeyLen := 0
	matchedKeys := make([]string, 0)

	iter := p.ac.Iter(tmpContent)
	for next := iter.Next(); next != nil; next = iter.Next() {
		tmp := p.allKeyArr[next.Pattern()]
		matchedKeys = append(matchedKeys, tmp)
		allKeyLen += len(tmp)
	}
	isCMD := len(tmpContent) <= allKeyLen

	// 避免同类型指令重复
	arrMap := make(map[rune]struct{})
	var matchedCmdArr []string
	if p.distinct && isCMD {
		matchedCmdArr = make([]string, 0, len(matchedKeys))
		for _, s := range matchedKeys {
			sRune := []rune(s)
			if _, ok := arrMap[sRune[0]]; !ok {
				arrMap[sRune[0]] = struct{}{}
				matchedCmdArr = append(matchedCmdArr, s)
			}
		}
	}
	resp := &CMD{IsCMD: isCMD, Arr: matchedKeys}
	if p.distinct {
		resp.Arr = matchedCmdArr
	}
	return resp
}