/****************************************************************************
 * Copyright (c) 2020.10 ~ 2022 liangxiegame UNDER MIT LICENSE
 * 
 * https://qframework.cn
 * https://github.com/liangxiegame/QFramework
 * https://gitee.com/liangxiegame/QFramework
 ****************************************************************************/

using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

// ReSharper disable once CheckNamespace
namespace QFramework
{
	public abstract class Table<TDataItem> : IEnumerable<TDataItem>, IDisposable
	{
		public void Add(TDataItem item)
		{
			OnAdd(item);
		}

		public void Remove(TDataItem item)
		{
			OnRemove(item);
		}

		public void Clear()
		{
			OnClear();
		}

		// 改,由于 TDataItem 是引用类型,所以直接改值即可。
		public void Update()
		{
		}

		protected abstract void OnAdd(TDataItem item);
		protected abstract void OnRemove(TDataItem item);

		protected abstract void OnClear();


		public abstract IEnumerator<TDataItem> GetEnumerator();

		IEnumerator IEnumerable.GetEnumerator()
		{
			return GetEnumerator();
		}

		public void Dispose()
		{
			OnDispose();
		}

		protected abstract void OnDispose();
	}
	
	 public class TableIndex<TKeyType, TDataItem>: IDisposable
        {
            private Dictionary<TKeyType, List<TDataItem>> mIndex = new Dictionary<TKeyType, List<TDataItem>>();
    
            private Func<TDataItem, TKeyType> mGetKeyByDataItem = null;
    
            public TableIndex(Func<TDataItem, TKeyType> keyGetter)
            {
                mGetKeyByDataItem = keyGetter;
            }
    
            public IDictionary<TKeyType, List<TDataItem>> Dictionary
            {
                get { return mIndex; }
            }
    
            public void Add(TDataItem dataItem)
            {
                var key = mGetKeyByDataItem(dataItem);
    
                if (mIndex.ContainsKey(key))
                {
                    mIndex[key].Add(dataItem);
                }
                else
                {
                    var list = ListPool<TDataItem>.Get();
    
                    list.Add(dataItem);
    
                    mIndex.Add(key, list);
                }
            }
    
            public void Remove(TDataItem dataItem)
            {
                var key = mGetKeyByDataItem(dataItem);
    
                mIndex[key].Remove(dataItem);
            }
    
            public IEnumerable<TDataItem> Get(TKeyType key)
            {
                List<TDataItem> retList = null;
    
                if (mIndex.TryGetValue(key, out retList))
                {
                    return retList;
                }
    
                // 返回一个空的集合
                return Enumerable.Empty<TDataItem>();
            }
    
            public void Clear()
            {
                foreach (var value in mIndex.Values)
                {
                    value.Clear();
                }
    
                mIndex.Clear();
            }
            
    
            public void Dispose()
            {
                foreach (var value in mIndex.Values)
                {
                    value.Release2Pool();
                }
    
                mIndex.Release2Pool();
    
                mIndex = null;
            }
        }
	 
	 
	 /// <summary>
	 /// 链表对象池:存储相关对象
	 /// </summary>
	 /// <typeparam name="T"></typeparam>
	 internal static class ListPool<T>
	 {
		 /// <summary>
		 /// 栈对象:存储多个List
		 /// </summary>
		 static Stack<List<T>> mListStack = new Stack<List<T>>(8);

		 /// <summary>
		 /// 出栈:获取某个List对象
		 /// </summary>
		 /// <returns></returns>
		 public static List<T> Get()
		 {
			 if (mListStack.Count == 0)
			 {
				 return new List<T>(8);
			 }

			 return mListStack.Pop();
		 }

		 /// <summary>
		 /// 入栈:将List对象添加到栈中
		 /// </summary>
		 /// <param name="toRelease"></param>
		 public static void Release(List<T> toRelease)
		 {
			 toRelease.Clear();
			 mListStack.Push(toRelease);
		 }
	 }

	 /// <summary>
	 /// 链表对象池 拓展方法类
	 /// </summary>
	 internal static class ListPoolExtensions
	 {
		 /// <summary>
		 /// 给List拓展 自身入栈 的方法
		 /// </summary>
		 /// <typeparam name="T"></typeparam>
		 /// <param name="toRelease"></param>
		 public static void Release2Pool<T>(this List<T> toRelease)
		 {
			 ListPool<T>.Release(toRelease);
		 }
	 }
	 
	 /// <summary>
	 /// 字典对象池:用于存储相关对象
	 /// </summary>
	 /// <typeparam name="TKey"></typeparam>
	 /// <typeparam name="TValue"></typeparam>
	 internal class DictionaryPool<TKey, TValue>
	 {
		 /// <summary>
		 /// 栈对象:存储多个字典
		 /// </summary>
		 static Stack<Dictionary<TKey, TValue>> mListStack = new Stack<Dictionary<TKey, TValue>>(8);

		 /// <summary>
		 /// 出栈:从栈中获取某个字典数据
		 /// </summary>
		 /// <returns></returns>
		 public static Dictionary<TKey, TValue> Get()
		 {
			 if (mListStack.Count == 0)
			 {
				 return new Dictionary<TKey, TValue>(8);
			 }

			 return mListStack.Pop();
		 }

		 /// <summary>
		 /// 入栈:将字典数据存储到栈中 
		 /// </summary>
		 /// <param name="toRelease"></param>
		 public static void Release(Dictionary<TKey, TValue> toRelease)
		 {
			 toRelease.Clear();
			 mListStack.Push(toRelease);
		 }
	 }
    
	 /// <summary>
	 /// 对象池字典 拓展方法类
	 /// </summary>
	 internal static class DictionaryPoolExtensions
	 {
		 /// <summary>
		 /// 对字典拓展 自身入栈 的方法
		 /// </summary>
		 /// <typeparam name="TKey"></typeparam>
		 /// <typeparam name="TValue"></typeparam>
		 /// <param name="toRelease"></param>
		 public static void Release2Pool<TKey,TValue>(this Dictionary<TKey, TValue> toRelease)
		 {
			 DictionaryPool<TKey,TValue>.Release(toRelease);
		 }
	 }
}