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

using System;
using System.Threading;
using System.Linq;

namespace System.Collections.Generic
{
    /// <summary>
    /// (线程安全)最近访问优先集合
    /// </summary>
    public class LatestPriorityDictionary<TKey, TValue> : IDictionary<TKey, TValue>
    {
        private Dictionary<TKey, CacheItem> _CacheItems;
        private SortedList<DateTime, TKey> _CacheKeys;
        private int _Capacity;
        private static readonly object _SyncRoot = new object();

        /// <summary>
        /// 初始化集合，默认大小为15
        /// </summary>
        public LatestPriorityDictionary()
            : this(15)
        {
        }

        /// <summary>
        /// 用指定的容量初始化集合
        /// </summary>
        /// <param name="capacity"></param>
        public LatestPriorityDictionary(int capacity)
        {
            _Capacity = capacity;
            _CacheItems = new Dictionary<TKey, LatestPriorityDictionary<TKey, TValue>.CacheItem>(capacity);
            _CacheKeys = new SortedList<DateTime, TKey>();
        }

        /// <summary>
        /// 删除掉指定个数的早期被添加或被访问的元素
        /// </summary>
        /// <param name="count"></param>
        private void RemoveEarliestItems(int count)
        {
            count = Math.Min(this.Count, count);
            for (int i = count - 1; i >= 0; i--)
            {
                TKey key = this._CacheKeys.Values[0];
				this._CacheItems.Remove(key);
				this._CacheKeys.RemoveAt(0);
            }
        }

        /// <summary>
        /// 刷新指定键所对应的访问时间
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private DateTime RefreshAccessTime(TKey key)
        {
            DateTime latest = DateTime.MinValue;
            DateTime accessTime = DateTime.Now;
            int count = this._CacheKeys.Count;
            if (count > 0)
            {
                latest = _CacheKeys.Keys[count - 1];
                if (accessTime <= latest)
                {
                    accessTime = latest.AddMilliseconds(1f);
                }
            }

            if (_CacheKeys.Values.Contains(key))
            {
                _CacheKeys.Remove(_CacheItems[key].AccessTime);
            }
            _CacheKeys.Add(accessTime, key);

            return accessTime;
        }

        #region IDictionary<TKey,TValue> 成员

        /// <summary>
        /// 添加一个带有所提供的键和值的元素。
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        public void Add(TKey key, TValue value)
        {
            lock(_SyncRoot)
            {
                if (!_CacheItems.ContainsKey(key))
                {
                    DateTime accessTime = this.RefreshAccessTime(key);
                    _CacheItems[key] = new CacheItem(value.Clone<TValue>(), accessTime);

                    if (this.Count > this._Capacity)
                    {
                        this.RemoveEarliestItems(this.Count - this._Capacity);
                    }
                }
            }
        }

        /// <summary>
        /// 确定是否包含特定值。
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool ContainsKey(TKey key)
        {
            lock (_SyncRoot)
            {
                return _CacheItems.ContainsKey(key);
            }
        }

        /// <summary>
        /// 获取集合当中所有的键的集合
        /// </summary>
        public ICollection<TKey> Keys
        {
            get
            {
                lock (_SyncRoot)
                {
                    return _CacheItems.Keys;
                }
            }
        }

        /// <summary>
        /// 删除指定的元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(TKey key)
        {
            lock (_SyncRoot)
            {
                if (_CacheItems.ContainsKey(key))
                {
                    CacheItem item = _CacheItems[key];
                    return  _CacheItems.Remove(key) &&
                    _CacheKeys.Remove(item.AccessTime);
                }
                return false;
            }
        }

        public bool TryGetValue(TKey key, out TValue value)
        {
            lock (_SyncRoot)
            {
                value = default(TValue);
                CacheItem item;
                bool result = _CacheItems.TryGetValue(key, out item);
                if (item != null)
                {
                    value = item.Value;
                }
                return result;
            }
        }

        /// <summary>
        /// 获取集合当中所有的值的集合
        /// </summary>
        public ICollection<TValue> Values
        {
            get
            {
                lock (_SyncRoot)
                {
                    return _CacheItems.Values
                        .ToList<CacheItem>()
                        .ConvertAll<TValue>(p => { return p.Value; });
                }
            }
        }

        /// <summary>
        /// 获取或设置键值对应的值
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public TValue this[TKey key]
        {
            get
            {
                TValue result = default(TValue);
                lock (_SyncRoot)
                {
                    if (_CacheItems.ContainsKey(key))
                    {
                        result = _CacheItems[key].Value;
                        _CacheItems[key].AccessTime = this.RefreshAccessTime(key);
                    }
                }
                return result.Clone<TValue>();
            }
            set
            {
                lock (_SyncRoot)
                {
                    DateTime accessTime = this.RefreshAccessTime(key);
                    _CacheItems[key] = new CacheItem(value.Clone<TValue>(), accessTime);
                }
            }
        }

        #endregion

        #region ICollection<KeyValuePair<TKey,TValue>> 成员

        public void Add(KeyValuePair<TKey, TValue> item)
        {
            this.Add(item.Key, item.Value);
        }

        /// <summary>
        /// 移除集合当中所有的元素
        /// </summary>
        public void Clear()
        {
            lock(_SyncRoot)
            {
                _CacheItems.Clear();
                _CacheKeys.Clear();
            }
        }

        public bool Contains(KeyValuePair<TKey, TValue> item)
        {
            return this.ContainsKey(item.Key);
        }

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            lock (_SyncRoot)
            {
                List<KeyValuePair<TKey, TValue>> list = new List<KeyValuePair<TKey, TValue>>(this.Count);
                foreach (KeyValuePair<TKey, CacheItem> item in _CacheItems)
                {
                    list.Add(new KeyValuePair<TKey, TValue>(item.Key, item.Value.Value));
                }
                list.CopyTo(array, arrayIndex);
            }
        }

        /// <summary>
        /// 获取集合当中的元素个数
        /// </summary>
        public int Count
        {
            get
            {
                lock (_SyncRoot)
                {
                    return _CacheItems.Count;
                }
            }
        }

        /// <summary>
        /// 获取集合是否为只读
        /// </summary>
        public bool IsReadOnly
        {
            get { return false; }
        }

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            return this.Remove(item.Key);
        }

        #endregion

        #region IEnumerable<KeyValuePair<TKey,TValue>> 成员

        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            List<KeyValuePair<TKey, TValue>> list = new List<KeyValuePair<TKey, TValue>>(this.Count);
            foreach (KeyValuePair<TKey, CacheItem> item in _CacheItems)
            {
                list.Add(new KeyValuePair<TKey, TValue>(item.Key, item.Value.Value));
            }
            return list.GetEnumerator();
        }

        #endregion

        #region IEnumerable 成员

        /// <summary>
        /// 返回集合值的枚举器
        /// </summary>
        /// <returns></returns>
        IEnumerator IEnumerable.GetEnumerator()
        {
            return _CacheItems.Values.GetEnumerator();
        }

        #endregion

        /// <summary>
        /// 获取用于线程同步的根
        /// </summary>
        public object SyncRoot
        {
            get
            {
                return _SyncRoot;
            }
        }

        /// <summary>
        /// 集合缓存对象
        /// </summary>
        internal class CacheItem
        {
            /// <summary>
            /// 以时间、对象值初始化缓存对象
            /// </summary>
            /// <param name="value"></param>
            /// <param name="accessTime"></param>
            public CacheItem(TValue value, DateTime accessTime)
            {
                Value = value;
                AccessTime = accessTime;
            }

            /// <summary>
            /// 元素值
            /// </summary>
            public TValue Value { get; set; }

            /// <summary>
            /// 元素被访问的时刻
            /// </summary>
            public DateTime AccessTime { get; set; }
        }
    }

}
