package net.ranides.assira.text;

import net.ranides.assira.reflection.ResolveStrategy;

import java.util.regex.Pattern;

/**
 * {@link ResolveFormat} class can use different dialects for putting variable expressions inside text.
 * For example, variable could be written as {@code {variable}} or by {@code $variable}.
 *
 * Additionally, different dialects can define different behaviour if unknown variable is found.
 * For example, it could return "null" or just ignore expression, or throw exception.
 */
public enum ResolveDialect {

    /**
     * Default dialect uses format: {variable,format,options}
     * If variable expression is invalid, it is unaffected
     */
    DEFAULT(ResolveStrategy.FORMAT, "(\\{)(.+?)(?:,(.+?))?(?:,(.+?))?(\\})"),

    /**
     * Handlebars dialect uses format: {{variable/format/options}}
     * If variable expression is invalid, it is unaffected
     */
    HANDLEBARS(ResolveStrategy.HANDLEBARS, "(\\{{2,3})(.+?)(?:/(.+?))?(?:/(.+?))?(\\}{2,3})"),

    /**
     * Shell dialect uses format: ${variable,format,options}
     * If variable expression is invalid, exception is thrown
     */
    SHELL(ResolveStrategy.THROW, "\\$(\\{)(.+?)(?:,(.+?))?(?:,(.+?))?(\\})", "\\\\\\$(\\{)(.+?)(?:,(.+?))?(?:,(.+?))?(\\})"),
    ;

    private final Pattern pattern;

    private final Pattern escaped;

    private final ResolveStrategy strategy;

    ResolveDialect(ResolveStrategy strategy, String pattern) {
        this.strategy = strategy;
        this.pattern = Pattern.compile(pattern);
        this.escaped = Pattern.compile(pattern);
    }

    ResolveDialect(ResolveStrategy strategy, String pattern, String escaped) {
        this.strategy = strategy;
        this.pattern = Pattern.compile(pattern);
        this.escaped = Pattern.compile(escaped);
    }

    /**
     * This pattern is used to find "variable expression" inside ordinary string
     *
     * @return Pattern
     */
    public Pattern pattern() {
        return pattern;
    }

    /**
     * This pattern is used to find "variable expression" inside "regex escaped" string
     *
     * That means:
     * sometimes you want to escape all special regex characters inside string first, and then find
     * "variable expression" inside it. To do so, you should use "escaped" pattern.
     *
     * @return Pattern
     */
    public Pattern escaped() {
        return escaped;
    }

    /**
     * Returns ResolveStrategy used by this dialect
     *
     * @return ResolveStrategy
     */
    public ResolveStrategy strategy() {
        return strategy;
    }

}
