using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Text.Json.Serialization;
using System.Text.Json;
using System.Threading.Tasks;
using System.Collections;

namespace trieTree.xiaoshi.sz.com
{
    public class trieTree
    {
        treeNode root = new treeNode();
        Hashtable keyAddress = new Hashtable();

        public void AddWord(string word,string Key)
        {
            treeNode temNode = root;
            for (int i = 0; i < word.Length; i++)
            {
                if (temNode != null && temNode.children.ContainsKey(word[i]))
                {
                    temNode = (treeNode)temNode.children[word[i]];
                }
                else
                {
                    treeNode treeNode = new treeNode(word[i]);
                    temNode.children.Add(word[i], treeNode);
                    temNode = treeNode;
                }
            }

            temNode.isEnd = true;
            if (temNode.EndValues == null)
            {
                temNode.EndValues = new List<string>();
            }

            if (!temNode.EndValues.Contains(Key))
            {
                temNode.EndValues.Add(Key);
            }

            if (!keyAddress.ContainsKey(Key.Substring(0,12)))
            {
                keyAddress.Add(Key.Substring(0,12),word);
            }
        }

        public bool Search(string word,out List<string> key)
        {
            key = null;
            treeNode temNode = root;
            for (int i = 0; i < word.Length; i++)
            {
                if (temNode != null && temNode.children.ContainsKey(word[i]))
                {
                    temNode = (treeNode)temNode.children[word[i]];
                }
                else
                {
                    return false;
                }
            }

            if (temNode != null)
            {
                if (temNode.isEnd)
                {
                    key = temNode.EndValues;
                    return true;
                }
                else
                {
                    return false;
                }
            }
            else
            {
                return false ;
            }
        }

        /// <summary>
        /// 词库中最长匹配
        /// </summary>
        /// <param name="word"></param>
        /// <returns></returns>
        public treeNode maxPrif(string word,out int index)
        {
            treeNode retNode = null;
            index = -1;
            treeNode temNode = root;
            for (int i = 0; i < word.Length; i++)
            {
                if (temNode != null && temNode.children.ContainsKey(word[i]))
                {
                    temNode = (treeNode)temNode.children[word[i]];
                    if(temNode.isEnd)
                    {
                        retNode = temNode;
                        index = i;
                    }
                }
                else
                {
                    break;
                }
            }

            return retNode;


        }

        public void Save(string filePath)
        {
            
            using (FileStream stream = new FileStream(filePath, FileMode.Create))
            {
                stream.Write(DataContractFormatSerializer.Serialize<treeNode>(root, true));
            }

            using (FileStream stream = new FileStream(filePath+".key", FileMode.Create))
            {
                stream.Write(DataContractFormatSerializer.Serialize<Hashtable>(keyAddress, true));
            }
        }

        public void Load(string filePath)
        {
            using (FileStream stream = new FileStream(filePath, FileMode.Open))
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                root = (treeNode)DataContractFormatSerializer.Deserialize<treeNode>(bytes,true);
            }

            using (FileStream stream = new FileStream(filePath + ".key", FileMode.Open))
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                keyAddress  = (Hashtable)DataContractFormatSerializer.Deserialize<Hashtable>(bytes, true);
            }
        }

        public List<string> formatAddress(List<string> list)
        {
            List<string> retList = new List<string>();

            if (list != null && list.Count > 0)
            {
                string strAddress = list[list.Count - 1];
                String strKey = strAddress.Substring(0, 12);
                retList.Add((String)keyAddress[strKey.Substring(0, 2) + "0000000000"]);
                if (!strKey.EndsWith("0000000000"))
                {
                    if (!retList.Contains((String)keyAddress[strKey.Substring(0, 4) + "00000000"]))
                        retList.Add((String)keyAddress[strKey.Substring(0, 4) + "00000000"]);
                }

                if (!strKey.EndsWith("00000000")) 
                {
                    if (!retList.Contains((String)keyAddress[strKey.Substring(0, 6) + "000000"]))
                        retList.Add((String)keyAddress[strKey.Substring(0, 6) + "000000"]);
                }

                if (!strKey.EndsWith("000000"))
                {
                    if (!retList.Contains((String)keyAddress[strKey.Substring(0, 9) + "000"]))
                        retList.Add((String)keyAddress[strKey.Substring(0, 9) + "000"]);
                }

                if (!strKey.EndsWith("000"))
                    retList.Add((String)keyAddress[strKey]);
            }
            return retList;
        }

    }
}
