package geosite

import "github.com/sagernet/sing-box/option"

type ItemType = uint8

const (
	RuleTypeDomain ItemType = iota
	RuleTypeDomainSuffix
	RuleTypeDomainKeyword
	RuleTypeDomainRegex
)

type Item struct {
	Type  ItemType
	Value string
}

func Compile(code []Item) option.DefaultRule {
	var domainLength int
	var domainSuffixLength int
	var domainKeywordLength int
	var domainRegexLength int
	for _, item := range code {
		switch item.Type {
		case RuleTypeDomain:
			domainLength++
		case RuleTypeDomainSuffix:
			domainSuffixLength++
		case RuleTypeDomainKeyword:
			domainKeywordLength++
		case RuleTypeDomainRegex:
			domainRegexLength++
		}
	}
	var codeRule option.DefaultRule
	if domainLength > 0 {
		codeRule.Domain = make([]string, 0, domainLength)
	}
	if domainSuffixLength > 0 {
		codeRule.DomainSuffix = make([]string, 0, domainSuffixLength)
	}
	if domainKeywordLength > 0 {
		codeRule.DomainKeyword = make([]string, 0, domainKeywordLength)
	}
	if domainRegexLength > 0 {
		codeRule.DomainRegex = make([]string, 0, domainRegexLength)
	}
	for _, item := range code {
		switch item.Type {
		case RuleTypeDomain:
			codeRule.Domain = append(codeRule.Domain, item.Value)
		case RuleTypeDomainSuffix:
			codeRule.DomainSuffix = append(codeRule.DomainSuffix, item.Value)
		case RuleTypeDomainKeyword:
			codeRule.DomainKeyword = append(codeRule.DomainKeyword, item.Value)
		case RuleTypeDomainRegex:
			codeRule.DomainRegex = append(codeRule.DomainRegex, item.Value)
		}
	}
	return codeRule
}

func Merge(rules []option.DefaultRule) option.DefaultRule {
	var domainLength int
	var domainSuffixLength int
	var domainKeywordLength int
	var domainRegexLength int
	for _, subRule := range rules {
		domainLength += len(subRule.Domain)
		domainSuffixLength += len(subRule.DomainSuffix)
		domainKeywordLength += len(subRule.DomainKeyword)
		domainRegexLength += len(subRule.DomainRegex)
	}
	var rule option.DefaultRule
	if domainLength > 0 {
		rule.Domain = make([]string, 0, domainLength)
	}
	if domainSuffixLength > 0 {
		rule.DomainSuffix = make([]string, 0, domainSuffixLength)
	}
	if domainKeywordLength > 0 {
		rule.DomainKeyword = make([]string, 0, domainKeywordLength)
	}
	if domainRegexLength > 0 {
		rule.DomainRegex = make([]string, 0, domainRegexLength)
	}
	for _, subRule := range rules {
		if len(subRule.Domain) > 0 {
			rule.Domain = append(rule.Domain, subRule.Domain...)
		}
		if len(subRule.DomainSuffix) > 0 {
			rule.DomainSuffix = append(rule.DomainSuffix, subRule.DomainSuffix...)
		}
		if len(subRule.DomainKeyword) > 0 {
			rule.DomainKeyword = append(rule.DomainKeyword, subRule.DomainKeyword...)
		}
		if len(subRule.DomainRegex) > 0 {
			rule.DomainRegex = append(rule.DomainRegex, subRule.DomainRegex...)
		}
	}
	return rule
}