using System;
using System.Collections.Generic;

namespace Chernobyl.Values
{
    /// <summary>
    /// A type that acts as a basic implementation of <see cref="IDynamicContainer{T}"/>.
    /// This type can be used on its own to offer notifications of changes to 
    /// the value held by the type or make the creation of new
    /// <see cref="IDynamicContainer{T}"/> types easier.
    /// </summary>
    /// <typeparam name="T">The type being held within this instance.</typeparam>
    public class DynamicContainer<T> : BasicContainer<T>, IDynamicContainer<T>
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="DynamicContainer{T}"/> class
        /// that uses the default value of <typeparamref name="T"/> for 
        /// <see cref="Value"/> and 
        /// <see cref="System.Collections.Generic.Comparer{T}.Default"/> for the 
        /// <see cref="Comparer"/> property.
        /// </summary>
        public DynamicContainer() : this(default(T))
        {}

        /// <summary>
        /// Initializes a new instance of the <see cref="DynamicContainer{T}"/> class
        /// that uses <see cref="System.Collections.Generic.Comparer{T}.Default"/> 
        /// for the <see cref="Comparer"/>
        /// property.
        /// </summary>
        /// <param name="value">The value held by this instance.</param>
        public DynamicContainer(T value)
            : this(value, EqualityComparer<T>.Default)
        {}

        /// <summary>
        /// Initializes a new instance of the <see cref="DynamicContainer{T}"/> class.
        /// </summary>
        /// <param name="value">The value held by this instance.</param>
        /// <param name="comparer">The instance used to compare new and previous 
        /// values of <see cref="Value"/> to determine if 
        /// <see cref="IValue{T}.Provide"/> should be raised.</param>
        /// <exception cref="ArgumentNullException">Thrown if 
        /// <paramref name="comparer"/> is null.</exception>
        public DynamicContainer(T value, IEqualityComparer<T> comparer)
            : base(value, comparer)
        {}

        /// <summary>
        /// The value held by this instance. If the value has not yet been
        /// provided it will be equal to <c>default(T)</c>.
        /// </summary>
        public new T Value
        {
            get { return base.Value; }
            set { base.Value = value; }
        }

        /// <summary>
        /// The instance used to compare new and previous values of
        /// <see cref="Value"/> to determine if <see cref="IValue{T}.Provide"/> 
        /// should be raised.
        /// </summary>
        /// <exception cref="ArgumentNullException">Thrown if the value set on
        /// this property is null.</exception>
        public new IEqualityComparer<T> Comparer
        {
            get { return base.Comparer; }
            set { base.Comparer = value; }
        }
    }
}