package com.inspect.base.core.utils;

import com.inspect.base.core.text.Convert;

import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class ReUtil {
    public static final Pattern GROUP_VAR = Pattern.compile("\\$(\\d+)");
    public static final Set<Character> RE_KEYS = new HashSet<>(Arrays.asList('$', Character.valueOf('('), Character.valueOf(')'), Character.valueOf('*'), Character.valueOf('+'), Character.valueOf('.'), Character.valueOf('['), Character.valueOf(']'), Character.valueOf('?'), Character.valueOf('\\'), Character.valueOf('^'), Character.valueOf('{'), Character.valueOf('}'), Character.valueOf('|')));

    public static String replaceAll(CharSequence content, String regex, String replacementTemplate) {
        Pattern pattern = Pattern.compile(regex, 32);
        return replaceAll(content, pattern, replacementTemplate);
    }

    public static String replaceAll(CharSequence content, Pattern pattern, String replacementTemplate) {
        if (StringUtils.isEmpty((CharSequence) content)) {
            return "";
        } else {
            Matcher matcher = pattern.matcher(content);
            boolean result = matcher.find();
            if (!result) {
                return Convert.toStr(content);
            } else {
                Set<String> varNums = (Set) findAll(GROUP_VAR, replacementTemplate, 1, new HashSet());
                StringBuffer sb = new StringBuffer();

                do {
                    String replacement = replacementTemplate;

                    String var;
                    int group;
                    for (Iterator<String> iterator = varNums.iterator(); iterator.hasNext(); replacement = replacement.replace("$" + var, matcher.group(group))) {
                        var = iterator.next();
                        group = Integer.parseInt(var);
                    }

                    matcher.appendReplacement(sb, escape(replacement));
                    result = matcher.find();
                } while (result);

                matcher.appendTail(sb);
                return sb.toString();
            }
        }
    }

    public static <T extends Collection<String>> T findAll(Pattern pattern, CharSequence content, int group, T collection) {
        if (null != pattern && null != content) {
            if (null == collection) {
                throw new NullPointerException("Null collection param provided!");
            } else {
                Matcher matcher = pattern.matcher(content);

                while (matcher.find()) {
                    collection.add(matcher.group(group));
                }

                return collection;
            }
        } else {
            return null;
        }
    }

    public static String escape(char c) {
        StringBuilder builder = new StringBuilder();
        if (RE_KEYS.contains(c)) {
            builder.append('\\');
        }

        builder.append(c);
        return builder.toString();
    }

    public static String escape(CharSequence content) {
        if (StringUtils.isBlank(content)) {
            return "";
        } else {
            StringBuilder builder = new StringBuilder();
            int len = content.length();

            for (int i = 0; i < len; ++i) {
                char current = content.charAt(i);
                if (RE_KEYS.contains(current)) {
                    builder.append('\\');
                }

                builder.append(current);
            }

            return builder.toString();
        }
    }
}
