using CommonLang.IO;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using System.Collections;
using CommonLang.Log;

namespace CommonLang
{
    public class HashMap<K, V> : Dictionary<K, V>
    {
        public HashMap() { }
        public HashMap(int capacity) : base(capacity) { }
        public HashMap(IEqualityComparer<K> comparer) : base(comparer) { }
        public HashMap(int capacity, IEqualityComparer<K> comparer) : base(capacity, comparer) { }
        public HashMap(IDictionary<K, V> map) : base(map) { }
        public HashMap(IDictionary<K, V> map, IEqualityComparer<K> comparer) : base(map, comparer) { }

        public V Get(K key)
        {
            V ret;
            if (base.TryGetValue(key, out ret))
            {
                return ret;
            }
            return default(V);
        }

        public void Put(K key, V val)
        {
            this[key] = val;
        }
        /// <summary>
        /// 添加成功返回true
        /// </summary>
        /// <param name="key"></param>
        /// <param name="val"></param>
        /// <returns></returns>
        public bool TryAdd(K key, V val)
        {
            if (!this.ContainsKey(key))
            {
                this[key] = val;
                return true;
            }
            return false;
        }

        public V RemoveByKey(K key)
        {
            V ret;
            if (base.TryGetValue(key, out ret))
            {
                base.Remove(key);
            }
            return ret;
        }

        public void PutAll(IDictionary<K, V> map)
        {
            foreach (KeyValuePair<K, V> e in map)
            {
                Put(e.Key, e.Value);
            }
        }
    }

    public class ForEachHashMap<K, V> : IDictionary<K, V>
    {
        public V this[K key]
        {
            get
            {
                throw new NotImplementedException();
            }

            set
            {
                throw new NotImplementedException();
            }
        }

        public int Count
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public bool IsReadOnly
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public ICollection<K> Keys
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public ICollection<V> Values
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public void Add(KeyValuePair<K, V> item)
        {
            throw new NotImplementedException();
        }

        public void Add(K key, V value)
        {
            throw new NotImplementedException();
        }

        public void Clear()
        {
            throw new NotImplementedException();
        }

        public bool Contains(KeyValuePair<K, V> item)
        {
            throw new NotImplementedException();
        }

        public bool ContainsKey(K key)
        {
            throw new NotImplementedException();
        }

        public void CopyTo(KeyValuePair<K, V>[] array, int arrayIndex)
        {
            throw new NotImplementedException();
        }

        public IEnumerator<KeyValuePair<K, V>> GetEnumerator()
        {
            throw new NotImplementedException();
        }

        public bool Remove(KeyValuePair<K, V> item)
        {
            throw new NotImplementedException();
        }

        public bool Remove(K key)
        {
            throw new NotImplementedException();
        }

        public bool TryGetValue(K key, out V value)
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }
    }

    public class Properties : HashMap<string, string>
    {
        public static Properties LoadFromResource(string path, string separator = "=")
        {
            string text = Resource.LoadAllText(path);
            if (text != null)
            {
                Properties ret = new Properties();
                ret.ParseText(text, separator);
                return ret;
            }
            else
            {
                return null;
            }
        }

        public void AddAll(NameValueCollection config)
        {
            foreach (string key in config.AllKeys)
            {
                this[key] = config[key];
            }
        }
        public int ParseText(string text, string separator = "=")
        {
            string[] lines = text.Split(new char[] { '\n' });
            return ParseLines(lines, separator);
        }
        public int ParseLines(string[] lines, string separator = "=")
        {
            int count = 0;
            string line = null;
            for (int i = 0; i < lines.Length; i++)
            {
                if (line != null)
                {
                    line += lines[i].Trim();
                }
                else
                {
                    line = lines[i].Trim();
                }
                if (line.EndsWith("\\"))
                {
                    line = line.Substring(0, line.Length - 1);
                    if ((i + 1) < lines.Length)
                    {
                        ParseLine(line, separator);
                        count++;
                    }
                    else
                    {
                        continue;
                    }
                }
                else if (ParseLine(line, separator))
                {
                    count++;
                }
                line = null;
            }
            return count;
        }
        public bool ParseLine(string line, string separator = "=")
        {
            line = line.Trim();
            if (line.StartsWith("#"))
            {
                return false;
            }
            int index = line.IndexOf(separator);
            if (index >= 0)
            {
                string key = line.Substring(0, index).Trim();
                string val = line.Substring(index + 1).Trim();
                this[key] = val;
                return true;
            }
            return false;
        }
        public string ToParseString(string separator = " = ")
        {
            StringBuilder sb = new StringBuilder();
            foreach (var kv in this)
            {
                sb.AppendLine(kv.Key + separator + kv.Value);
            }
            return sb.ToString();
        }


        /// <summary>
        /// 通常载入配置文件
        /// </summary>
        /// <param name="cfg"></param>
        public void LoadFields(object cfg)
        {
            Type type = cfg.GetType();
            foreach (FieldInfo fi in type.GetFields())
            {
                if (!fi.IsStatic)
                {
                    if (ContainsKey(fi.Name))
                    {
                        string value = this.Get(fi.Name);
                        object vo = Parser.StringToObject(value, fi.FieldType);
                        fi.SetValue(cfg, vo);
                    }
                }
            }
        }
        public void SaveFields(object cfg)
        {
            Type type = cfg.GetType();
            foreach (FieldInfo fi in type.GetFields())
            {
                if (!fi.IsStatic)
                {
                    object vo = fi.GetValue(cfg);
                    this.Put(fi.Name, Parser.ObjectToString(vo));
                }
            }
        }
        public void LoadStaticFields(Type type)
        {
            foreach (FieldInfo fi in type.GetFields())
            {
                if (fi.IsStatic)
                {
                    if (ContainsKey(fi.Name))
                    {
                        string value = this.Get(fi.Name);
                        object vo = Parser.StringToObject(value, fi.FieldType);
                        fi.SetValue(null, vo);
                    }
                }
            }
        }
        public void SaveStaticFields(Type type)
        {
            foreach (FieldInfo fi in type.GetFields())
            {
                if (fi.IsStatic)
                {
                    object vo = fi.GetValue(null);
                    this.Put(fi.Name, Parser.ObjectToString(vo));
                }
            }
        }

        public Properties SubProperties(string prefix)
        {
            Properties ret = new Properties();
            foreach (string key in Keys)
            {
                try
                {
                    if (key.StartsWith(prefix))
                    {
                        string value = this[key];
                        string fname = key.Substring(prefix.Length);
                        ret[fname] = value;
                    }
                }
                catch (Exception err)
				{
					Console.WriteLine("SubProperties : " + prefix + ", catch: " + err);
				}
            }
            return ret;
        }



        public static void SaveStaticFieldsToFile(string file, Type type)
        {
            var prop = new CommonLang.Properties();
            prop.SaveStaticFields(type);
            System.IO.File.WriteAllText(file, prop.ToParseString(), CUtils.UTF8);
        }
        public static void LoadStaticFieldsFromFile(string file, Type type)
        {
            if (System.IO.File.Exists(file))
            {
                var text = System.IO.File.ReadAllText(file, CUtils.UTF8);
                if (text != null)
                {
                    var prop = new CommonLang.Properties();
                    prop.ParseText(text);
                    prop.LoadStaticFields(type);
                }
            }
        }
    }


    public class SyncMessageQueue<T>
    {
        private LinkedList<T> adding = new LinkedList<T>();

        private Logger log = LoggerFactory.GetLogger("SyncMessageQueue");
        /// <summary>
        /// 添加一个消息到队列
        /// </summary>
        /// <param name="item"></param>
        public void Enqueue(T item)
        {
            lock (adding)
            {
                adding.AddLast(item);
            }
        }

        /// <summary>
        /// 尝试处理队列中所有消息
        /// </summary>
        /// <param name="action">处理函数</param>
        public void ProcessMessages(Action<T> action)
        {
            var num = adding.Count;
            T act;
            while (num-- > 0)
            {
                lock (adding)
                {
                    if (adding.Count <= 0) return;
                    act = adding.First.Value;
                    adding.RemoveFirst();
                }
                action(act);
            }
        }


        public void Clear()
        {
            lock (adding)
            {
                this.adding.Clear();
            }
        }
    }


    public class SyncMessageQueueAction<T>
    {
        private LinkedList<Action<T>> adding = new LinkedList<Action<T>>();

        /// <summary>
        /// 添加一个消息到队列
        /// </summary>
        /// <param name="item"></param>
        public void Enqueue(Action<T> item)
        {
            lock (adding)
            {
                adding.AddLast(item);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="param"></param>
        public void ProcessMessages(T param)
        {
            var num = adding.Count;
            Action<T> act;
            while (num-- > 0)
            {
                lock (adding)
                {
                    if (adding.Count <= 0) return;
                    act = adding.First.Value;
                    adding.RemoveFirst();
                }
                act.Invoke(param);
            }
        }

        public void Clear()
        {
            lock (adding)
            {
                adding.Clear();
            }
        }
    }

    public class SyncMessageQueue2
    {
        private readonly LinkedList<Action> adding = new LinkedList<Action>();

        private readonly Action<Exception> errorHandler;

        public SyncMessageQueue2(Action<Exception> eh = null)
        {
            this.errorHandler = eh;
        }

        /// <summary>
        /// 添加一个消息到队列
        /// </summary>
        /// <param name="item"></param>
        public void Enqueue(Action item)
        {
            lock (adding)
            {
                adding.AddLast(item);
            }
        }

        private static long GetTime()
        {
            DateTime time197011 = new DateTime(1970, 1, 1);
            DateTime time = DateTime.Now;
            TimeSpan ts = time - time197011;
            TimeZone localZone = TimeZone.CurrentTimeZone;
            TimeSpan off = localZone.GetUtcOffset(time);
            ts -= off;
            return (long)ts.TotalMilliseconds;
        }

        /// <summary>
        /// 尝试处理队列中所有消息
        /// </summary>
        public void ProcessMessages()
        {
            lock (adding)
            {
                if (adding == null || adding.Count <= 0) return;
                long Begtime = (long)(DateTime.Now.Ticks * 0.0001);//GetTime();
                long curTime = Begtime;
                var num = adding.Count;
                while (num > 0 && adding.Count > 0)
                {
                    try
                    {
                        if (adding.Count <= 0) return;
                        Action act = adding.First.Value;
                        adding.RemoveFirst();
                        act.Invoke();
                    }
                    catch (Exception err)
                    {
                        errorHandler(err);
                        break;
                    }
                    num--;

                    curTime = (long)(DateTime.Now.Ticks * 0.0001);
                    if (curTime - Begtime > 100)
                    {
                        break;
                    }
                }
            }
           
        }

        public void Clear()
        {
            lock (adding)
            {
                this.adding.Clear();
            }
        }
    }

    public interface IOnceInvoke
    {
        bool IsDone { get; }
    }

    public class OnceInvokeList<T>
        where T : IOnceInvoke
    {
        private List<T> mInvokeList = new List<T>();
        public int Count { get { return mInvokeList.Count; } }
        public void Add(T e) { mInvokeList.Add(e); }

        public void Invoke(Action<T> on_invoke)
        {
            if (mInvokeList.Count > 0)
            {
                using (var list = ListObjectPool<T>.AllocAutoRelease(mInvokeList))
                {
                    foreach (var e in list)
                    {
                        on_invoke(e);
                    }
                }
                for (int i = mInvokeList.Count - 1; i >= 0; --i)
                {
                    var e = mInvokeList[i];
                    if (e.IsDone)
                    {
                        mInvokeList.RemoveAt(i);
                    }
                }
            }
        }
        public void Clear()
        {
            mInvokeList.Clear();
        }
    }

    public abstract class FastLinkNode
    {
        public FastLinkNode Prev { get { return m_prev; } }
        public FastLinkNode Next { get { return m_next; } }

        // 当前所在的列表
        internal object m_curList;
        internal FastLinkNode m_prev = null;
        internal FastLinkNode m_next = null;
    }

    public class FastLinkList<T> : ICollection<T> where T : FastLinkNode
    {
        private FastLinkNode head = null;
        private FastLinkNode last = null;
        private int count = 0;

        public T Head { get { return (T)head; } }
        public T Last { get { return (T)last; } }
        public bool IsEmpty { get { return count == 0; } }
        public bool IsReadOnly { get { return false; } }
        public int Count { get { return count; } }

        public void Add(T node)
        {
            if (node.m_curList == null)
            {
                if (last == null)
                {
                    head = last = node;
                }
                else
                {
                    last.m_next = node;
                    node.m_prev = last;
                    last = node;
                }
                node.m_curList = this;
                count++;
            }
            else
            {
                throw new Exception("Node is already in a List !");
            }
        }

        public bool Remove(T node)
        {
            if (node.m_curList == this)
            {
                if (head == node)
                {
                    head = node.m_next;
                }
                if (last == node)
                {
                    last = node.m_prev;
                }
                if (node.m_next != null)
                {
                    node.m_next.m_prev = node.m_prev;
                }
                if (node.m_prev != null)
                {
                    node.m_prev.m_next = node.m_next;
                }
                node.m_next = null;
                node.m_prev = null;
                node.m_curList = null;
                count--;
                return true;
            }
            else
            {
                throw new Exception("Node is not contains in this list !");
            }
        }

        public void Clear()
        {
            if (count > 0)
            {
                for (FastLinkNode i = head; i != null; i = i.m_next)
                {
                    i.m_curList = null;
                }
                FastLinkNode p = head;
                FastLinkNode q = null;
                do
                {
                    q = p.m_next;
                    p.m_next = null;
                    p = q;
                }
                while (p != null);
                p = last;
                do
                {
                    q = p.m_prev;
                    p.m_prev = null;
                    p = q;
                }
                while (p != null);
                head = null;
                last = null;
                count = 0;
            }
        }

        public bool Contains(T item)
        {
            return item.m_curList == this;
        }

        public void CopyTo(T[] array, int arrayIndex)
        {
            for (FastLinkNode i = head; i != null; i = i.m_next)
            {
                array[arrayIndex] = (T)i;
                arrayIndex++;
            }
        }

        public IEnumerator<T> GetEnumerator()
        {
            return new Enumerator(this);
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return new Enumerator(this);
        }

        public struct Enumerator : IEnumerator<T>
        {
            private FastLinkList<T> list;
            private T current;
            public Enumerator(FastLinkList<T> list)
            {
                this.list = list;
                this.current = null;
            }
            public T Current
            {
                get { return current; }
            }
            object System.Collections.IEnumerator.Current
            {
                get { return current; }
            }

            public void Dispose()
            {
                current = null;
            }

            public bool MoveNext()
            {
                if (current == null)
                {
                    this.current = (T)list.Head;
                }
                else
                {
                    this.current = (T)current.Next;
                }
                return current != null;
            }

            public void Reset()
            {
                this.current = null;
            }
        }
    }



}