package validator

import (
	"regexp"
	"strings"
)

// V is a validator implementation
type V struct {
	spamlist []*regexp.Regexp
	enforce  Enforce
	from     string
	log      Logger
}

// Enforce checks
type Enforce struct {
	// Email enforces email check and rejects empty emails
	Email bool
	// Domain enforces domain check and rejects empty domains
	Domain bool
	// SMTP enforces SMTP check (email actually exists on mail server) and rejects non-existing emails
	SMTP bool
	// SPF enforces SPF record check (sender allowed to use that email and send emails) and rejects unathorized emails
	SPF bool
	// MX enforces MX records check on email's mail server
	MX bool
}

type Logger interface {
	Info(string, ...interface{})
	Error(string, ...interface{})
}

// New Validator, accepts spamlist with wildcards
func New(spamlist []string, enforce Enforce, smtpFrom string, log Logger) *V {
	spamregexes, err := parseSpamlist(spamlist)
	if err != nil {
		log.Error("cannot parse spamlist: %v", err)
	}

	return &V{
		spamlist: spamregexes,
		enforce:  enforce,
		from:     smtpFrom,
		log:      log,
	}
}

func parseSpamlist(patterns []string) ([]*regexp.Regexp, error) {
	regexes := []*regexp.Regexp{}
	for _, pattern := range patterns {
		rule, err := regexp.Compile("^" + parsePattern(pattern) + "$")
		if err != nil {
			return regexes, err
		}

		regexes = append(regexes, rule)
	}

	return regexes, nil
}

func parsePattern(pattern string) string {
	var regexpattern strings.Builder
	for _, runeItem := range pattern {
		if runeItem == '*' {
			regexpattern.WriteString("(.*)")
			continue
		}
		regexpattern.WriteString(regexp.QuoteMeta(string(runeItem)))
	}

	return regexpattern.String()
}
