/*
 * ReadOnlyDictionary.cs --
 *
 * Copyright (c) 2007-2012 by Joe Mistachkin.  All rights reserved.
 *
 * See the file "license.terms" for information on usage and redistribution of
 * this file, and for a DISCLAIMER OF ALL WARRANTIES.
 *
 * RCS: @(#) $Id: $
 */

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Eagle._Attributes;

namespace Eagle._Containers.Public
{
    [ObjectId("a18619fe-ebf2-4b1e-9a04-5262ba53b89e")]
    public class ReadOnlyDictionary<TKey, TValue> :
            IDictionary<TKey, TValue>, IDictionary
    {
        #region Private Data
        //
        // NOTE: This is the dictionary that we are wrapping.
        //
        private Dictionary<TKey, TValue> genericDictionary;

        ///////////////////////////////////////////////////////////////////////

        //
        // NOTE: These interface variables also point to the dictionary we are
        //       wrapping.
        //
        private ICollection<KeyValuePair<TKey, TValue>> genericCollection;
        private IDictionary dictionary;
        private ICollection collection;
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Private Methods
        private void SetupPrivateData()
        {
            //
            // NOTE: Cast the contained dictionary to the other interfaces we
            //       need.
            //
            genericCollection = genericDictionary as
                ICollection<KeyValuePair<TKey, TValue>>;

            dictionary = genericDictionary as IDictionary;
            collection = genericDictionary as ICollection;
        }

        ///////////////////////////////////////////////////////////////////////

        private ReadOnlyCollection<TKey> GetKeys()
        {
            return new ReadOnlyCollection<TKey>(new List<TKey>(
                genericDictionary.Keys));
        }

        ///////////////////////////////////////////////////////////////////////

        private ReadOnlyCollection<TValue> GetValues()
        {
            return new ReadOnlyCollection<TValue>(new List<TValue>(
                genericDictionary.Values));
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region Public Constructors
        [Obsolete()] // WARNING: Creates an empty read-only dictionary.
        public ReadOnlyDictionary()
        {
            genericDictionary = new Dictionary<TKey, TValue>();
            SetupPrivateData();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReadOnlyDictionary(
            IDictionary<TKey, TValue> dictionary
            )
        {
            genericDictionary = new Dictionary<TKey, TValue>(dictionary);
            SetupPrivateData();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReadOnlyDictionary(
            IEqualityComparer<TKey> comparer
            )
        {
            genericDictionary = new Dictionary<TKey, TValue>(comparer);
            SetupPrivateData();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReadOnlyDictionary(
            int capacity
            )
        {
            genericDictionary = new Dictionary<TKey, TValue>(capacity);
            SetupPrivateData();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReadOnlyDictionary(
            IDictionary<TKey, TValue> dictionary,
            IEqualityComparer<TKey> comparer
            )
        {
            genericDictionary = new Dictionary<TKey, TValue>(
                dictionary, comparer);

            SetupPrivateData();
        }

        ///////////////////////////////////////////////////////////////////////

        public ReadOnlyDictionary(
            int capacity,
            IEqualityComparer<TKey> comparer
            )
        {
            genericDictionary = new Dictionary<TKey, TValue>(
                capacity, comparer);

            SetupPrivateData();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDictionary<TKey,TValue> Members
        public void Add(TKey key, TValue value)
        {
            throw new NotSupportedException();
        }

        ///////////////////////////////////////////////////////////////////////

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

        ///////////////////////////////////////////////////////////////////////

        public ICollection<TKey> Keys
        {
            get { return GetKeys(); }
        }

        ///////////////////////////////////////////////////////////////////////

        public bool Remove(TKey key)
        {
            throw new NotSupportedException();
        }

        ///////////////////////////////////////////////////////////////////////

        public bool TryGetValue(TKey key, out TValue value)
        {
            return genericDictionary.TryGetValue(key, out value);
        }

        ///////////////////////////////////////////////////////////////////////

        public ICollection<TValue> Values
        {
            get { return GetValues(); }
        }

        ///////////////////////////////////////////////////////////////////////

        public TValue this[TKey key]
        {
            get { return genericDictionary[key]; }
            set { throw new NotSupportedException(); }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region ICollection<KeyValuePair<TKey,TValue>> Members
        public void Add(KeyValuePair<TKey, TValue> item)
        {
            throw new NotSupportedException();
        }

        ///////////////////////////////////////////////////////////////////////

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

        ///////////////////////////////////////////////////////////////////////

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

        ///////////////////////////////////////////////////////////////////////

        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
        {
            genericCollection.CopyTo(array, arrayIndex);
        }

        ///////////////////////////////////////////////////////////////////////

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

        ///////////////////////////////////////////////////////////////////////

        public bool IsReadOnly
        {
            get { return true; }
        }

        ///////////////////////////////////////////////////////////////////////

        public bool Remove(KeyValuePair<TKey, TValue> item)
        {
            throw new NotSupportedException();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IDictionary Members
        public void Add(object key, object value)
        {
            throw new NotSupportedException();
        }

        ///////////////////////////////////////////////////////////////////////

        public bool Contains(object key)
        {
            return dictionary.Contains(key);
        }

        ///////////////////////////////////////////////////////////////////////

        IDictionaryEnumerator IDictionary.GetEnumerator()
        {
            return dictionary.GetEnumerator();
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsFixedSize
        {
            get { return dictionary.IsFixedSize; }
        }

        ///////////////////////////////////////////////////////////////////////

        ICollection IDictionary.Keys
        {
            get { return GetKeys(); }
        }

        ///////////////////////////////////////////////////////////////////////

        public void Remove(object key)
        {
            throw new NotSupportedException();
        }

        ///////////////////////////////////////////////////////////////////////

        ICollection IDictionary.Values
        {
            get { return GetValues(); }
        }

        ///////////////////////////////////////////////////////////////////////

        public object this[object key]
        {
            get { return dictionary[key]; }
            set { throw new NotSupportedException(); }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region ICollection Members
        public void CopyTo(Array array, int index)
        {
            collection.CopyTo(array, index);
        }

        ///////////////////////////////////////////////////////////////////////

        public bool IsSynchronized
        {
            get { return collection.IsSynchronized; }
        }

        ///////////////////////////////////////////////////////////////////////

        public object SyncRoot
        {
            get { return collection.SyncRoot; }
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IEnumerable<KeyValuePair<TKey,TValue>> Members
        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
        {
            return genericDictionary.GetEnumerator();
        }
        #endregion

        ///////////////////////////////////////////////////////////////////////

        #region IEnumerable Members
        IEnumerator IEnumerable.GetEnumerator()
        {
            return genericDictionary.GetEnumerator();
        }
        #endregion
    }
}
