/*
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.text;

import java.io.Serializable;
import java.nio.file.Path;
import java.util.function.Predicate;
import java.util.regex.Pattern;

/**
 * Wildcard class is simple Predicate which accepts CharSequences matching to the pattern.
 * Pattern consists of standard glob operators: * and ?
 *
 * @author Ranides Atterwim {@literal <ranides@gmail.com>}
 */
public final class Wildcard implements Serializable, Predicate<CharSequence> {
	
	private static final long serialVersionUID = 2L;	
	
	private final Pattern re;

	private Wildcard(Pattern re) {
		this.re = re;
	}

	/**
	 * Creates new wildcard matching to pattern.
	 * Supported special characters: * for any text, ? for any char
	 *
	 * @param pattern pattern
	 * @return Wildcard
	 */
	public static Wildcard compile(String pattern) {
		return compile(pattern,0);
	}

	/**
	 * Creates new wildcard matching to pattern.
	 * Supported special characters: * for any text, ? for any char
	 *
	 * Accepts flags supported by {@link Pattern}.
	 *
	 * @param pattern pattern
	 * @param flags flags
	 * @return Wildcard
	 */
	public static Wildcard compile(String pattern, int flags) {
        String p = StringUtils.escapeRE(pattern)
            .replace("\\*", ".*")
            .replace("\\?",".");
		return new Wildcard(Pattern.compile(p, flags));
	}

	/**
	 * Returns true if provided pattern matches provided text.
	 *
	 * @param pattern pattern
	 * @param text text
	 * @return boolean
	 */
    public static boolean match(String pattern, String text) {
        return compile(pattern).test(text);
    }

	@Override // NOPMD
	public boolean test(CharSequence text) {
		return re.matcher(text).matches();
	}

	/**
	 * Returns Pattern which is equivalent to this Wildcard.
	 *
	 * @return Pattern
	 */
	public Pattern asPattern() {
		return re;
	}

	/**
	 * Returns Predicate which tests paths instead of Strings.
	 *
	 * Only filename part inside Path is tested against pattern.
	 *
	 * @return Predicate
	 */
	public Predicate<Path> asPathFilter() {
		return f -> test(f.getFileName().toString());
	}
	
}
