#region Copyright notice and license
// Copyright 2015, Google Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endregion

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Collections.Specialized;
using System.Runtime.InteropServices;
using System.Text;

using Grpc.Core.Utils;

namespace Grpc.Core
{
    /// <summary>
    /// Provides access to read and write metadata values to be exchanged during a call.
    /// </summary>
    public sealed class Metadata : IList<Metadata.Entry>
    {
        /// <summary>
        /// An read-only instance of metadata containing no entries.
        /// </summary>
        public static readonly Metadata Empty = new Metadata().Freeze();

        readonly List<Entry> entries;
        bool readOnly;

        public Metadata()
        {
            this.entries = new List<Entry>();
        }

        public Metadata(ICollection<Entry> entries)
        {
            this.entries = new List<Entry>(entries);
        }

        /// <summary>
        /// Makes this object read-only.
        /// </summary>
        /// <returns>this object</returns>
        public Metadata Freeze()
        {
            this.readOnly = true;
            return this;
        }

        // TODO: add support for access by key

        #region IList members

        public int IndexOf(Metadata.Entry item)
        {
            return entries.IndexOf(item);
        }

        public void Insert(int index, Metadata.Entry item)
        {
            CheckWriteable();
            entries.Insert(index, item);
        }

        public void RemoveAt(int index)
        {
            CheckWriteable();
            entries.RemoveAt(index);
        }

        public Metadata.Entry this[int index]
        {
            get
            {
                return entries[index];
            }

            set
            {
                CheckWriteable();
                entries[index] = value;
            }
        }

        public void Add(Metadata.Entry item)
        {
            CheckWriteable();
            entries.Add(item);
        }

        public void Clear()
        {
            CheckWriteable();
            entries.Clear();
        }

        public bool Contains(Metadata.Entry item)
        {
            return entries.Contains(item);
        }

        public void CopyTo(Metadata.Entry[] array, int arrayIndex)
        {
            entries.CopyTo(array, arrayIndex);
        }

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

        public bool IsReadOnly
        {
            get { return readOnly; }
        }

        public bool Remove(Metadata.Entry item)
        {
            CheckWriteable();
            return entries.Remove(item);
        }

        public IEnumerator<Metadata.Entry> GetEnumerator()
        {
            return entries.GetEnumerator();
        }

        IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return entries.GetEnumerator();
        }

        private void CheckWriteable()
        {
            Preconditions.CheckState(!readOnly, "Object is read only");
        }

        #endregion

        /// <summary>
        /// Metadata entry
        /// </summary>
        public struct Entry
        {
            private static readonly Encoding Encoding = Encoding.ASCII;

            readonly string key;
            string value;
            byte[] valueBytes;

            public Entry(string key, byte[] valueBytes)
            {
                this.key = Preconditions.CheckNotNull(key);
                this.value = null;
                this.valueBytes = Preconditions.CheckNotNull(valueBytes);
            }

            public Entry(string key, string value)
            {
                this.key = Preconditions.CheckNotNull(key);
                this.value = Preconditions.CheckNotNull(value);
                this.valueBytes = null;
            }

            public string Key
            {
                get
                {
                    return this.key;
                }
            }

            public byte[] ValueBytes
            {
                get
                {
                    if (valueBytes == null)
                    {
                        valueBytes = Encoding.GetBytes(value);
                    }
                    return valueBytes;
                }
            }

            public string Value
            {
                get
                {
                    if (value == null)
                    {
                        value = Encoding.GetString(valueBytes);
                    }
                    return value;
                }
            }
                
            public override string ToString()
            {
                return string.Format("[Entry: key={0}, value={1}]", Key, Value);
            }
        }
    }
}
