// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

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

namespace Microsoft.AspNetCore.Connections
{
    /// <summary>
    /// The items associated with a given connection.
    /// </summary>
    public class ConnectionItems : IDictionary<object, object?>
    {
        /// <summary>
        /// Initializes a new instance of <see cref="ConnectionItems"/>.
        /// </summary>
        public ConnectionItems()
            : this(new Dictionary<object, object?>())
        {
        }

        /// <summary>
        /// Initializes a new instance of <see cref="ConnectionItems"/> with <paramref name="items"/>.
        /// </summary>
        /// <param name="items">The items for the connection.</param>
        public ConnectionItems(IDictionary<object, object?> items)
        {
            Items = items;
        }

        /// <summary>
        /// Gets or sets the items for the connection.
        /// </summary>
        public IDictionary<object, object?> Items { get; }

        // Replace the indexer with one that returns null for missing values
        object? IDictionary<object, object?>.this[object key]
        {
            get
            {
                if (Items.TryGetValue(key, out var value))
                {
                    return value;
                }
                return null;
            }
            set { Items[key] = value; }
        }

        void IDictionary<object, object?>.Add(object key, object? value)
        {
            Items.Add(key, value);
        }

        bool IDictionary<object, object?>.ContainsKey(object key)
        {
            return Items.ContainsKey(key);
        }

        ICollection<object> IDictionary<object, object?>.Keys
        {
            get { return Items.Keys; }
        }

        bool IDictionary<object, object?>.Remove(object key)
        {
            return Items.Remove(key);
        }

        bool IDictionary<object, object?>.TryGetValue(object key, out object? value)
        {
            return Items.TryGetValue(key, out value);
        }

        ICollection<object?> IDictionary<object, object?>.Values
        {
            get { return Items.Values; }
        }

        void ICollection<KeyValuePair<object, object?>>.Add(KeyValuePair<object, object?> item)
        {
            Items.Add(item);
        }

        void ICollection<KeyValuePair<object, object?>>.Clear()
        {
            Items.Clear();
        }

        bool ICollection<KeyValuePair<object, object?>>.Contains(KeyValuePair<object, object?> item)
        {
            return Items.Contains(item);
        }

        void ICollection<KeyValuePair<object, object?>>.CopyTo(KeyValuePair<object, object?>[] array, int arrayIndex)
        {
            Items.CopyTo(array, arrayIndex);
        }

        int ICollection<KeyValuePair<object, object?>>.Count
        {
            get { return Items.Count; }
        }

        bool ICollection<KeyValuePair<object, object?>>.IsReadOnly
        {
            get { return Items.IsReadOnly; }
        }

        bool ICollection<KeyValuePair<object, object?>>.Remove(KeyValuePair<object, object?> item)
        {
            if (Items.TryGetValue(item.Key, out var value) && Equals(item.Value, value))
            {
                return Items.Remove(item.Key);
            }
            return false;
        }

        IEnumerator<KeyValuePair<object, object?>> IEnumerable<KeyValuePair<object, object?>>.GetEnumerator()
        {
            return Items.GetEnumerator();
        }

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