package com.cm.plugin.manager;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * When you feel like quitting. Think about why you started
 * 当你想要放弃的时候，想想当初你为何开始
 *
 * @ClassName: SensitiveWordsManager
 * @Description: 敏感词管理
 * @Author: WangGeng
 * @Date: 2020/6/17 4:39 下午
 * @Version: 1.0
 **/
public class SensitiveWordsManager {

    private static final Logger LOG = LoggerFactory.getLogger(SensitiveWordsManager.class);
    private static SensitiveWordsManager sensitiveWordsManager = SensitiveWordsManagerBuilder.sensitiveWordsManager;
    private Map<String, Object> sensitiveWordMap = new ConcurrentHashMap<>(16);
    public static final String KEY_IS_END = "isEnd";
    public static final String KEY_DEPTH = "depth";

    private SensitiveWordsManager() {
    }

    public static SensitiveWordsManager getInstance() {
        return sensitiveWordsManager;
    }

    /**
     * 初始化敏感词
     *
     * @param sensitiveWordList 敏感词列表
     */
    public void initSensitiveWords(List<String> sensitiveWordList) {
        LOG.debug("初始化敏感词列表");
        sensitiveWordMap.clear();
        if (sensitiveWordList == null || sensitiveWordList.isEmpty()) {
            LOG.debug("初始化敏感词列表为空");
            return;
        }
        for (String sensitiveWord : sensitiveWordList) {
            Map<String, Object> tempSensitiveWordMap = sensitiveWordMap;
            int depth = 0;
            for (int i = 0; i < sensitiveWord.length(); i++) {
                char word = sensitiveWord.charAt(i);
                String wordString = String.valueOf(word);
                Map<String, Object> wordMap = (Map<String, Object>) tempSensitiveWordMap.get(wordString);
                if (wordMap == null) {
                    Map<String, Object> newWordMap = new ConcurrentHashMap<>(16);
                    newWordMap.put(KEY_IS_END, 0);
                    newWordMap.put(KEY_DEPTH, depth++);
                    tempSensitiveWordMap.put(wordString, newWordMap);
                    tempSensitiveWordMap = newWordMap;
                } else {
                    tempSensitiveWordMap = wordMap;
                    depth++;
                }
                if (i == sensitiveWord.length() - 1) {
                    tempSensitiveWordMap.put(KEY_IS_END, 1);
                }
            }
        }
        LOG.debug("敏感词列表初始化成功");
    }

    /**
     * 获取敏感词结果
     *
     * @param content
     * @return
     */
    public SensitiveResult getSensitiveWordsResult(String content) {
        if (StringUtils.isBlank(content)) {
            return null;
        }
        String result = content.replaceAll("(\\w)[\\s|　]+(\\w)", "$1@$2").replaceAll("\\s+", "").replaceAll("@", " ");
        List<SensitiveWordsResult> sensitiveWordsResults = new ArrayList<>();
        SensitiveResult sensitiveResult = new SensitiveResult();
        sensitiveResult.setSensitive(result);
        sensitiveResult.setSensitiveWordsResults(sensitiveWordsResults);
        if (sensitiveWordMap.isEmpty()) {
            return sensitiveResult;
        }
        Map<String, Object> tempMap = sensitiveWordMap;
        StringBuilder sensitiveWord = new StringBuilder();
        int depth = 0;
        for (char word : result.toCharArray()) {
            String wordString = String.valueOf(word).toLowerCase();
            Map<String, Object> wordMap = (Map<String, Object>) tempMap.get(wordString);
            if (wordMap == null) {
                tempMap = sensitiveWordMap;
                continue;
            }
            tempMap = wordMap;
            if (depth == (int) wordMap.get(KEY_DEPTH)) {
                sensitiveWord.append(wordString);
                depth++;
            } else {
                depth = 0;
                sensitiveWord = new StringBuilder();
                sensitiveWord.append(wordString);
                depth++;
                continue;
            }
            if ((int) wordMap.get(KEY_IS_END) == 1) {
                sensitiveWordsResults.add(new SensitiveWordsResult(sensitiveWord.toString()));
                depth = 0;
                sensitiveWord = new StringBuilder();
            }
        }
        return sensitiveResult;
    }

    /**
     * 返回敏感过滤结果，替换成相应字符
     *
     * @param content
     * @param replace
     * @return
     */
    public String getSensitiveWordsResultWithReplace(String content, char replace) {
        SensitiveResult sensitiveResult = getSensitiveWordsResult(content);
        if (sensitiveResult == null) {
            return null;
        }
        List<SensitiveWordsResult> sensitiveWordsResults = sensitiveResult.getSensitiveWordsResults();
        if (sensitiveWordsResults.isEmpty()) {
            return sensitiveResult.getSensitive();
        }
        for (SensitiveWordsResult sensitiveWordsResult : sensitiveWordsResults) {
            String sensitiveWord = sensitiveWordsResult.getSensitiveWord();
            StringBuilder replaceSB = new StringBuilder();
            for (int i = 0; i < sensitiveWord.length(); i++) {
                replaceSB.append(replace);
            }
            sensitiveResult.setSensitive(sensitiveResult.getSensitive().replaceAll(sensitiveWord, replaceSB.toString()));
        }
        return sensitiveResult.getSensitive();
    }

    /**
     * 返回敏感过滤结果，替换成相应字符
     *
     * @param content
     * @param replace
     * @param sensitiveWords
     * @return
     */
    public String getSensitiveWordsResultWithReplace(String content, char replace, List<String> sensitiveWords) {
        if (StringUtils.isBlank(content)) {
            return null;
        }
        if (sensitiveWords == null || sensitiveWords.isEmpty()) {
            return content;
        }
        String result = content;
        for (String sensitiveWord : sensitiveWords) {
            StringBuilder replaceSB = new StringBuilder();
            for (int i = 0; i < sensitiveWord.length(); i++) {
                replaceSB.append(replace);
            }
            result = result.replaceAll(sensitiveWord, replaceSB.toString());
        }
        return result;
    }

    private static class SensitiveWordsManagerBuilder {
        public static SensitiveWordsManager sensitiveWordsManager = new SensitiveWordsManager();
    }

}
