package main

import "fmt"

func truthy(val interface{}) bool {
	switch v := val.(type) {
	case string:
		return v != ""
	case bool:
		return v
	case int:
		return v != 0
	}
	return false
}

// Templater for custom emails.
// Variables should be written as {varName}.
// If statements should be written as {if (!)varName}...{endif}.
// Strings are true if != "", ints are true if != 0.
func templateEmail(content string, variables []string, conditionals []string, values map[string]interface{}) string {
	ifStart, ifEnd := -1, -1
	ifTrue := false
	invalidIf := false
	previousEnd := -2
	cStart, cEnd := -1, -1
	varStart, varEnd := -1, -1
	varName := ""
	out := ""
	for i, c := range content {
		if c == '{' {
			cStart = i + 1
			for content[cStart] == ' ' {
				cStart++
			}
			if content[cStart:cStart+3] == "if " {
				varStart = cStart + 3
				for content[varStart] == ' ' {
					varStart++
				}
			}
			if ifStart == -1 {
				out += content[previousEnd+2 : i]
			}
			if content[cStart:cStart+5] != "endif" || invalidIf {
				continue
			}
			ifEnd = i - 1
			if ifTrue {
				out += templateEmail(content[ifStart:ifEnd+1], variables, conditionals, values)
				ifTrue = false
			}
		} else if c == '}' {
			if varStart != -1 {
				ifStart = i + 1
				varEnd = i - 1
				for content[varEnd] == ' ' {
					varEnd--
				}
				varName = content[varStart : varEnd+1]
				positive := true
				if varName[0] == '!' {
					positive = false
					varName = varName[1:]
				}
				validVar := false
				wrappedVarName := "{" + varName + "}"
				for _, v := range conditionals {
					if v == wrappedVarName {
						validVar = true
						break
					}
				}
				if validVar {
					ifTrue = positive == truthy(values[varName])
				} else {
					invalidIf = true
					ifStart, ifEnd = -1, -1
				}
				varStart, varEnd = -1, -1
			}
			cEnd = i - 1
			for content[cEnd] == ' ' {
				cEnd--
			}
			previousEnd = i - 1
			if content[cEnd-4:cEnd+1] == "endif" && !invalidIf {
				continue
			}
			validVar := false
			varName = content[cStart : cEnd+1]
			cStart, cEnd = -1, -1
			if ifStart != -1 {
				continue
			}
			wrappedVarName := "{" + varName + "}"
			for _, v := range variables {
				if v == wrappedVarName {
					validVar = true
					break
				}
			}
			if !validVar {
				out += wrappedVarName
				continue
			}
			out += fmt.Sprint(values[varName])
		}
	}
	if previousEnd+1 != len(content)-1 {
		out += content[previousEnd+2:]
	}
	if out == "" {
		return content
	}
	return out
}