#region COPYRIGHT
//
//     THIS IS GENERATED BY TEMPLATE
//     
//     AUTHOR  :     ROYE
//     DATE       :     2010
//
//     COPYRIGHT (C) 2010, TIANXIAHOTEL TECHNOLOGIES CO., LTD. ALL RIGHTS RESERVED.
//
#endregion

using System;

namespace System.Collections.Generic
{
    /// <summary>
    /// 提供一个同时支持按索引或键值访问的泛型集合
    /// </summary>
    /// <typeparam name="TKey">集合元素对应的键</typeparam>
    /// <typeparam name="TValue">集合元素</typeparam>
    public abstract class HashList<TKey, TValue> : IList<TValue>
    {
        private Dictionary<TKey, TValue> _InnerHash;
        private List<TValue> _InnerList;

        public HashList()
        {
            _InnerHash = new Dictionary<TKey, TValue>();
            _InnerList = new List<TValue>();
        }

        public HashList(int capacity)
        {
            _InnerHash = new Dictionary<TKey, TValue>(capacity);
            _InnerList = new List<TValue>(capacity);
        }

        public HashList(IEnumerable<TValue> collection)
            : this()
        {
            this.AddRange(collection);
        }

        /// <summary>
        /// 获取元素对应的键值
        /// </summary>
        /// <param name="item"></param>
        /// <returns></returns>
        protected abstract TKey GetKey(TValue item);

        /// <summary>
        /// 向现有集合添加一个对应类型的集合
        /// </summary>
        /// <param name="collection"></param>
        public void AddRange(IEnumerable<TValue> collection)
        {
            foreach (TValue item in collection)
            {
                this.Add(item);
            }
        }

        #region IList<TValue> 成员

        public int IndexOf(TValue item)
        {
            return _InnerList.IndexOf(item);
        }

        public void Insert(int index, TValue item)
        {
            if (item == null)
            {
                throw new ArgumentNullException("item");
            }

            TKey key = this.GetKey(item);
            if (!_InnerHash.ContainsKey(key))
            {
                _InnerHash[key] = item;
                _InnerList.Insert(index, item);
            }
        }

        public void RemoveAt(int index)
        {
            TValue item = _InnerList[index];
            if (item != null)
            {
                TKey key = this.GetKey(item);
                this._InnerHash.Remove(key);
                this._InnerList.RemoveAt(index);
            }
        }

        #endregion

        #region ICollection<TValue> 成员

        public void Add(TValue item)
        {
            TKey key = this.GetKey(item);
            if (!_InnerHash.ContainsKey(key))
            {
                _InnerHash[key] = item;
                _InnerList.Add(item);
            }
        }

        public void Clear()
        {
            if (this.Count > 0)
            {
                _InnerHash.Clear();
                _InnerList.Clear();
            }
        }

        public bool Contains(TValue item)
        {
            return _InnerHash.ContainsValue(item);
        }

        public void CopyTo(TValue[] array, int arrayIndex)
        {
            this._InnerList.CopyTo(array, arrayIndex);
        }

        public int Count
        {
            get { return _InnerList.Count; }
        }

        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(TValue item)
        {
            bool ok = false;

            TKey key = this.GetKey(item);
            if (_InnerHash.ContainsKey(key))
            {
                ok = _InnerHash.Remove(key)
                    & _InnerList.Remove(item);
            }

            return ok;
        }

        public bool Remove(TKey key)
        {
            bool ok = false;
            if (_InnerHash.ContainsKey(key))
            {
                var item = _InnerHash[key];
                ok = _InnerHash.Remove(key)
                    & _InnerList.Remove(item);
            }
            return ok;
        }

        #endregion

        #region IEnumerable<TValue> 成员

        public IEnumerator<TValue> GetEnumerator()
        {
            return this._InnerList.GetEnumerator();
        }

        #endregion

        #region IEnumerable 成员

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

        #endregion

        public bool ContainsKey(TKey key)
        {
            return _InnerHash.ContainsKey(key);
        }

        public TValue Find(Predicate<TValue> match)
        {
            return this._InnerList.Find(match);
        }

        public List<TValue> FindAll(Predicate<TValue> match)
        {
            return this._InnerList.FindAll(match);
        }

        public int FindIndex(Predicate<TValue> match)
        {
            return this._InnerList.FindIndex(match);
        }

        public int FindIndex(int startIndex, Predicate<TValue> match)
        {
            return this._InnerList.FindIndex(startIndex, match);
        }

        public int FindIndex(int startIndex, int count, Predicate<TValue> match)
        {
            return this._InnerList.FindIndex(startIndex, count, match);
        }

        public TValue FindLast(Predicate<TValue> match)
        {
            return this._InnerList.FindLast(match);
        }

        public int FindLastIndex(Predicate<TValue> match)
        {
            return this._InnerList.FindLastIndex(match);
        }

        public int FindLastIndex(int startIndex, Predicate<TValue> match)
        {
            return this._InnerList.FindLastIndex(startIndex, match);
        }

        public int FindLastIndex(int startIndex, int count, Predicate<TValue> match)
        {
            return this._InnerList.FindLastIndex(startIndex, count, match);
        }

        public int LastIndexOf(TValue item)
        {
            return this._InnerList.LastIndexOf(item);
        }

        public int LastIndexOf(TValue item, int index)
        {
            return this._InnerList.LastIndexOf(item, index);
        }

        public int LastIndexOf(TValue item, int index, int count)
        {
            return this._InnerList.LastIndexOf(item, index, count);
        }

        public void ForEach(Action<TValue> action)
        {
            this._InnerList.ForEach(action);
        }

        public TValue[] ToArray()
        {
            return this._InnerList.ToArray();
        }

        /// <summary>
        /// 获取或设置指定键值对应的元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TValue this[TKey key]
        {
            get
            {
                return this._InnerHash[key];
            }
            set
            {
                if (!this.Contains(value))
                {
                    this._InnerList.Add(value);
                    this._InnerHash[key] = value;
                }
            }
        }

        /// <summary>
        /// 获取或设置指定索引对应的元素
        /// </summary>
        /// <param name="index"></param>
        /// <returns></returns>
        public TValue this[int index]
        {
            get
            {
                return _InnerList[index];
            }
            set
            {
                if (!this.Contains(value))
                {
                    TKey oldKey = this.GetKey(this[index]);
                    TKey key = this.GetKey(value);
                    _InnerHash.Remove(oldKey);
                    _InnerHash[key] = value;
                    _InnerList[index] = value;
                }
            }
        }
    }
}

