package cn.com.ty.lift.ud.sensitivewords.service.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import cn.com.ty.lift.common.judge.Judge;
import cn.com.ty.lift.ud.common.SensitivewordFilter;
import cn.com.ty.lift.ud.redis.RedisUtil;
import cn.com.ty.lift.ud.sensitivewords.mapper.SensitiveWordsMapper;
import cn.com.ty.lift.ud.sensitivewords.mapper.entity.SensitiveWords;
import cn.com.ty.lift.ud.sensitivewords.service.ISensitiveWordsService;
import cn.com.xwy.boot.web.dto.RestResponse;
import cn.hutool.core.bean.BeanUtil;

/**
 * 敏感词汇 -ServiceImpl
 *
 * @author Xson
 * @date 2020-04-24
 */
@Service
@Transactional
public class SensitiveWordsServiceImpl extends ServiceImpl<SensitiveWordsMapper, SensitiveWords>
    implements ISensitiveWordsService {

    @Autowired
    private SensitiveWordsMapper sensitiveWordsMapper;
    
    private @Autowired RedisUtil redis ;

    @Override
    public void updateStatuzByIds(List<Long> ids, Integer status) {
        for (Long id : ids) {
            SensitiveWords bit = new SensitiveWords();
            bit.setId(id);
            bit.setStatus(status);
            sensitiveWordsMapper.updateById(bit);
        }
    }

    @Override
    public List<SensitiveWords> getAll() {
        return sensitiveWordsMapper.getAll();
    }

    @Override
    public Set<String> getAllToSet() {
        List<SensitiveWords> all = sensitiveWordsMapper.getAll();
        Set<String> set = new HashSet<>();
        for (SensitiveWords s : all) {
            set.add(s.getKeyword());
        }
        return set;
    }

    @Override
    public Set<String> changText(String text) {
        Set<String> sensitiveWordList = new HashSet<String>();
        for (int i = 0; i < text.length(); i++) {
            int length = CheckSensitiveWord(text, i, 1); // 判断是否包含敏感字符
            if (length > 0) { // 存在,加入list中
                sensitiveWordList.add(text.substring(i, i + length));
                i = i + length - 1; // 减1的原因，是因为for会自增
            }
        }

        return sensitiveWordList;
    }

    private Map addSensitiveWordToHashMap(Set<String> keyWordSet) {
        Map sensitiveWordMap = new HashMap(keyWordSet.size()); // 初始化敏感词容器，减少扩容操作
        String key = null;
        Map nowMap = null;
        Map<String, String> newWorMap = null;
        // 迭代keyWordSet
        Iterator<String> iterator = keyWordSet.iterator();
        while (iterator.hasNext()) {
            key = iterator.next(); // 关键字
            nowMap = sensitiveWordMap;
            for (int i = 0; i < key.length(); i++) {
                char keyChar = key.charAt(i); // 转换成char型
                Object wordMap = nowMap.get(keyChar); // 获取

                if (wordMap != null) { // 如果存在该key，直接赋值
                    nowMap = (Map)wordMap;
                } else { // 不存在则，则构建一个map，同时将isEnd设置为0，因为他不是最后一个
                    newWorMap = new HashMap<String, String>();
                    newWorMap.put("isEnd", "0"); // 不是最后一个
                    nowMap.put(keyChar, newWorMap);
                    nowMap = newWorMap;
                }

                if (i == key.length() - 1) {
                    nowMap.put("isEnd", "1"); // 最后一个
                }
            }
        }
        return sensitiveWordMap;
    }

    public int CheckSensitiveWord(String txt, int beginIndex, int matchType) {
        boolean flag = false; // 敏感词结束标识位：用于敏感词只有1位的情况
        int matchFlag = 0; // 匹配标识数默认为0
        char word = 0;
        List<SensitiveWords> all = sensitiveWordsMapper.getAll();
        Set<String> keyWordSet = new HashSet<>();
        for (SensitiveWords s : all) {
            keyWordSet.add(s.getKeyword());
        }
        Map nowMap = addSensitiveWordToHashMap(keyWordSet);
        Map mapByKey = null;
        for (int i = beginIndex; i < txt.length(); i++) {
            word = txt.charAt(i);
            System.out.println(nowMap);
            if (mapByKey == null) {
                mapByKey = (Map)nowMap.get(word); // 获取指定key
            } else {
                mapByKey = (Map)mapByKey.get(word);
            }
            System.out.println(mapByKey);
            if (mapByKey != null) { // 存在，则判断是否为最后一个
                matchFlag++; // 找到相应key，匹配标识+1
                if ("1".equals(mapByKey.get("isEnd"))) { // 如果为最后一个匹配规则,结束循环，返回匹配标识数
                    flag = true; // 结束标志位为true
                    if (SensitivewordFilter.minMatchTYpe == matchType) { // 最小规则，直接返回,最大规则还需继续查找
                        break;
                    }
                }
            } else { // 不存在，直接返回
                break;
            }
        }
        if (matchFlag < 1 || !flag) { // 长度必须大于等于1，为词
            matchFlag = 0;
        }
        return matchFlag;
    }

    @Transactional(rollbackFor = Exception.class)
    public RestResponse assemble(List<SensitiveWords> liftImportModels) {
        Judge.notNull(liftImportModels, "没有数据");
        // 存放新建的lift
        List<SensitiveWords> lifts = new ArrayList<>();

        liftImportModels.forEach(item -> {
            SensitiveWords lift = new SensitiveWords();
            // 复制解析model中的值到lift中
            BeanUtil.copyProperties(item, lift, true);

        });
        return RestResponse.success("导入成功");
    }

    @Override
    public Set<String> changText(String text, Integer matchType) {
        Set<String> sensitiveWordList = new HashSet<String>();
        for (int i = 0; i < text.length(); i++) {
            int length = CheckSensitiveWords(text, i, matchType); // 判断是否包含敏感字符
            if (length > 0) { // 存在,加入list中
                sensitiveWordList.add(text.substring(i, i + length));
                i = i + length - 1; // 减1的原因，是因为for会自增
            }
        }

        return sensitiveWordList;
    }
    
    
    private int CheckSensitiveWords(String txt, int beginIndex, int matchType) {
        boolean flag = false; // 敏感词结束标识位：用于敏感词只有1位的情况
        int matchFlag = 0; // 匹配标识数默认为0
        char word = 0;
        
       String sensitiveWords  = redis.getKey("sensitiveWords");
       List<SensitiveWords> all = null;
       if(StringUtils.isBlank(sensitiveWords)){
           all = sensitiveWordsMapper.getAll();
//           redis.setValue("sensitiveWords", all);
       }else{
           all = redis.get("sensitiveWords", List.class);
       }
       
       
        Set<String> keyWordSet = new HashSet<>();
        for (SensitiveWords s : all) {
            keyWordSet.add(s.getKeyword());
        }
        Map nowMap = addSensitiveWordToHashMap(keyWordSet);
        Map mapByKey = null;
        for (int i = beginIndex; i < txt.length(); i++) {
            word = txt.charAt(i);
//            System.out.println(nowMap);
            if (mapByKey == null) {
                mapByKey = (Map)nowMap.get(word); // 获取指定key
            } else {
                mapByKey = (Map)mapByKey.get(word);
            }
//            System.out.println(mapByKey);
            if (mapByKey != null) { // 存在，则判断是否为最后一个
                matchFlag++; // 找到相应key，匹配标识+1
                if ("1".equals(mapByKey.get("isEnd"))) { // 如果为最后一个匹配规则,结束循环，返回匹配标识数
                    flag = true; // 结束标志位为true
                    if (SensitivewordFilter.minMatchTYpe == matchType) { // 最小规则，直接返回,最大规则还需继续查找
                        break;
                    }
                }
            } else { // 不存在，直接返回
                break;
            }
        }
        if (matchFlag < 1 || !flag) { // 长度必须大于等于1，为词
            matchFlag = 0;
        }
        return matchFlag;
    }

    @Override
    public List<SensitiveWords> getByKeyword(String keyword) {
        return sensitiveWordsMapper.getByKeyword( keyword);
    }
}
