using System;
using System.Collections.Frozen;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace HuanMeng.DotNetCore.TextCensor.SensitiveWord
{
    public class SensitiveWordFilter : ITextCensor
    {
        /// <summary>
        /// 定义Trie树节点  
        /// </summary>
        private class TrieNode
        {
            /// <summary>
            ///  标记是否是一个敏感词的结尾
            /// </summary>
            public bool IsEnd { get; set; }
            /// <summary>
            ///  存储子节点
            /// </summary>
            public Dictionary<char, TrieNode> Children { get; set; }
            /// <summary>
            /// 
            /// </summary>
            //public FrozenDictionary<char, TrieNode> fChildren { get; set; }
            public TrieNode()
            {
                IsEnd = false;
                Children = new Dictionary<char, TrieNode>();
            }
        }

        /// <summary>
        /// 根节点
        /// </summary>
        private TrieNode Root { get; set; }
        public SensitiveWordFilter()
        {
            Root = new TrieNode();
        }
        /// <summary>
        /// 添加敏感词到Trie树中
        /// </summary>
        /// <param name="word"></param>
        public void AddSensitiveWord(string word)
        {
            TrieNode currentNode = Root;
            word = CleanText(word);
            foreach (char c in word.ToLower())
            {
                // 如果当前字符不存在于子节点中，则添加
                if (!currentNode.Children.ContainsKey(c))
                {
                    currentNode.Children[c] = new TrieNode();
                }
                currentNode = currentNode.Children[c];
            }
            currentNode.IsEnd = true;  // 标记当前节点为敏感词结尾
        }
        /// <summary>
        /// 定义要移除的字符集合，包括空格
        /// </summary>
        private static string replaceString = @"[ \.,。，@\-*12345690_]";
        /// <summary>
        /// 清理文字
        /// </summary>
        /// <param name="sourceTxt"></param>
        /// <returns></returns>
        public string CleanText(string sourceTxt)
        {
            if (string.IsNullOrEmpty(sourceTxt))
            {
                return string.Empty;
            }

            // 使用正则表达式替换所有匹配的字符
            //string cleanedText = Regex.Replace(sourceTxt.ToLower(), replaceString, string.Empty);
            string cleanedText = sourceTxt
                .Replace(',', ' ')
                .Replace('.', ' ')
                .Replace('。', ' ')
                .Replace('，', ' ')
                .Replace('@', ' ')
                .Replace('-', ' ')
                .Replace('*', ' ')
                .Replace("1", string.Empty)
                .Replace("2", string.Empty)
                .Replace("3", string.Empty)
                .Replace("4", string.Empty)
                .Replace("5", string.Empty)
                .Replace("6", string.Empty)
                .Replace("9", string.Empty)
                .Replace("0", string.Empty)
                .Replace("_", string.Empty)
                .Replace(" ", string.Empty).ToLower();
            return cleanedText;
        }

        /// <summary>
        /// 判断文本中是否包含敏感词
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public bool ContainsSensitiveWord(string text)
        {
            //过滤字符串
            text = CleanText(text);
            for (int i = 0; i < text.Length; i++)
            {
                TrieNode currentNode = Root;
                int j = i;
                // 从当前位置开始匹配敏感词
                while (j < text.Length && currentNode.Children.ContainsKey(text[j]))
                {
                    currentNode = currentNode.Children[text[j]];
                    // 如果当前节点是敏感词结尾，返回true
                    if (currentNode.IsEnd)
                    {
                        return true;
                    }
                    j++;
                }
            }
            return false;
        }

        public bool TextCensor(string text)
        {
            return ContainsSensitiveWord(text);
        }

        public Task<bool> TextCensorAsync(string text)
        {
            return Task.Run(() =>
              {
                  return ContainsSensitiveWord(text);
              });

        }
    }
}
