#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2015 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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.Generic;
using System.Security;

namespace Google.Protobuf
{
    /// <summary>
    /// Used to keep track of fields which were seen when parsing a protocol message
    /// but whose field numbers or types are unrecognized. This most frequently
    /// occurs when new fields are added to a message type and then messages containing
    /// those fields are read by old software that was built before the new types were
    /// added.
    ///
    /// Most users will never need to use this class directly.
    /// </summary>
    public sealed partial class UnknownFieldSet
    {
        private readonly IDictionary<int, UnknownField> fields = new Dictionary<int, UnknownField>();

        /// <summary>
        /// Creates a new UnknownFieldSet.
        /// </summary>
        internal UnknownFieldSet()
        {
        }

        /// <summary>
        /// Checks whether or not the given field number is present in the set.
        /// </summary>
        internal bool HasField(int field)
        {
            return fields.ContainsKey(field);
        }

        /// <summary>
        /// Serializes the set and writes it to <paramref name="output"/>.
        /// </summary>
        public void WriteTo(CodedOutputStream output)
        {
            WriteContext.Initialize(output, out WriteContext ctx);
            try
            {
                WriteTo(ref ctx);
            }
            finally
            {
                ctx.CopyStateTo(output);
            }
        }

        /// <summary>
        /// Serializes the set and writes it to <paramref name="ctx"/>.
        /// </summary>
        [SecuritySafeCritical]
        public void WriteTo(ref WriteContext ctx)
        {
            foreach (KeyValuePair<int, UnknownField> entry in fields)
            {
                entry.Value.WriteTo(entry.Key, ref ctx);
            }
        }

        /// <summary>
        /// Gets the number of bytes required to encode this set.
        /// </summary>
        public int CalculateSize()
        {
            int result = 0;
            foreach (KeyValuePair<int, UnknownField> entry in fields)
            {
                result += entry.Value.GetSerializedSize(entry.Key);
            }
            return result;
        }

        /// <summary>
        /// Checks if two unknown field sets are equal.
        /// </summary>
        public override bool Equals(object other)
        {
            if (ReferenceEquals(this, other))
            {
                return true;
            }
            UnknownFieldSet otherSet = other as UnknownFieldSet;
            IDictionary<int, UnknownField> otherFields = otherSet.fields;
            if (fields.Count  != otherFields.Count)
            {
                return false;
            }
            foreach (KeyValuePair<int, UnknownField> leftEntry in fields)
            {
                if (!otherFields.TryGetValue(leftEntry.Key, out UnknownField rightValue))
                {
                    return false;
                }
                if (!leftEntry.Value.Equals(rightValue))
                {
                    return false;
                }
            }
            return true;
        }

        /// <summary>
        /// Gets the unknown field set's hash code.
        /// </summary>
        public override int GetHashCode()
        {
            int ret = 1;
            foreach (KeyValuePair<int, UnknownField> field in fields)
            {
                // Use ^ here to make the field order irrelevant.
                int hash = field.Key.GetHashCode() ^ field.Value.GetHashCode();
                ret ^= hash;
            }
            return ret;
        }

        // Optimization:  We keep around the last field that was
        // modified so that we can efficiently add to it multiple times in a
        // row (important when parsing an unknown repeated field).
        private int lastFieldNumber;
        private UnknownField lastField;

        private UnknownField GetOrAddField(int number)
        {
            if (lastField != null && number == lastFieldNumber)
            {
                return lastField;
            }
            if (number == 0)
            {
                return null;
            }

            if (fields.TryGetValue(number, out UnknownField existing))
            {
                return existing;
            }
            lastField = new UnknownField();
            AddOrReplaceField(number, lastField);
            lastFieldNumber = number;
            return lastField;
        }

        /// <summary>
        /// Adds a field to the set. If a field with the same number already exists, it
        /// is replaced.
        /// </summary>
        internal UnknownFieldSet AddOrReplaceField(int number, UnknownField field)
        {
            if (number == 0)
            {
                throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
            }
            fields[number] = field;
            return this;
        }
        
        /// <summary>
        /// Parse a single field from <paramref name="ctx"/> and merge it
        /// into this set.
        /// </summary>
        /// <param name="ctx">The parse context from which to read the field</param>
        /// <returns>false if the tag is an "end group" tag, true otherwise</returns>
        private bool MergeFieldFrom(ref ParseContext ctx)
        {
            uint tag = ctx.LastTag;
            int number = WireFormat.GetTagFieldNumber(tag);
            switch (WireFormat.GetTagWireType(tag))
            {
                case WireFormat.WireType.Varint:
                    {
                        ulong uint64 = ctx.ReadUInt64();
                        GetOrAddField(number).AddVarint(uint64);
                        return true;
                    }
                case WireFormat.WireType.Fixed32:
                    {
                        uint uint32 = ctx.ReadFixed32();
                        GetOrAddField(number).AddFixed32(uint32);
                        return true;
                    }
                case WireFormat.WireType.Fixed64:
                    {
                        ulong uint64 = ctx.ReadFixed64();
                        GetOrAddField(number).AddFixed64(uint64);
                        return true;
                    }
                case WireFormat.WireType.LengthDelimited:
                    {
                        ByteString bytes = ctx.ReadBytes();
                        GetOrAddField(number).AddLengthDelimited(bytes);
                        return true;
                    }
                case WireFormat.WireType.StartGroup:
                    {
                        UnknownFieldSet set = new UnknownFieldSet();
                        ParsingPrimitivesMessages.ReadGroup(ref ctx, number, set);
                        GetOrAddField(number).AddGroup(set);
                        return true;
                    }
                case WireFormat.WireType.EndGroup:
                    {
                        return false;
                    }
                default:
                    throw InvalidProtocolBufferException.InvalidWireType();
            }
        }

        internal void MergeGroupFrom(ref ParseContext ctx)
        {
            while (true)
            {
                uint tag = ctx.ReadTag();
                if (tag == 0)
                {
                    break;
                }
                if (!MergeFieldFrom(ref ctx))
                {
                    break;
                }
            }
        }

        /// <summary>
        /// Create a new UnknownFieldSet if unknownFields is null.
        /// Parse a single field from <paramref name="input"/> and merge it
        /// into unknownFields. If <paramref name="input"/> is configured to discard unknown fields,
        /// <paramref name="unknownFields"/> will be returned as-is and the field will be skipped.
        /// </summary>
        /// <param name="unknownFields">The UnknownFieldSet which need to be merged</param>
        /// <param name="input">The coded input stream containing the field</param>
        /// <returns>The merged UnknownFieldSet</returns>
        public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields,
                                                     CodedInputStream input)
        {
            ParseContext.Initialize(input, out ParseContext ctx);
            try
            {
                return MergeFieldFrom(unknownFields, ref ctx);
            }
            finally
            {
                ctx.CopyStateTo(input);
            }
        }

        /// <summary>
        /// Create a new UnknownFieldSet if unknownFields is null.
        /// Parse a single field from <paramref name="ctx"/> and merge it
        /// into unknownFields. If <paramref name="ctx"/> is configured to discard unknown fields,
        /// <paramref name="unknownFields"/> will be returned as-is and the field will be skipped.
        /// </summary>
        /// <param name="unknownFields">The UnknownFieldSet which need to be merged</param>
        /// <param name="ctx">The parse context from which to read the field</param>
        /// <returns>The merged UnknownFieldSet</returns>
        [SecuritySafeCritical]
        public static UnknownFieldSet MergeFieldFrom(UnknownFieldSet unknownFields,
                                                     ref ParseContext ctx)
        {
            if (ctx.DiscardUnknownFields)
            {
                ParsingPrimitivesMessages.SkipLastField(ref ctx.buffer, ref ctx.state);
                return unknownFields;
            }
            if (unknownFields == null)
            {
                unknownFields = new UnknownFieldSet();
            }
            if (!unknownFields.MergeFieldFrom(ref ctx))
            {
                throw new InvalidProtocolBufferException("Merge an unknown field of end-group tag, indicating that the corresponding start-group was missing."); // match the old code-gen
            }
            return unknownFields;
        }

        /// <summary>
        /// Merges the fields from <paramref name="other"/> into this set.
        /// If a field number exists in both sets, the values in <paramref name="other"/>
        /// will be appended to the values in this set.
        /// </summary>
        private UnknownFieldSet MergeFrom(UnknownFieldSet other)
        {
            if (other != null)
            {
                foreach (KeyValuePair<int, UnknownField> entry in other.fields)
                {
                    MergeField(entry.Key, entry.Value);
                }
            }
            return this;
        }

        /// <summary>
        /// Created a new UnknownFieldSet to <paramref name="unknownFields"/> if
        /// needed and merges the fields from <paramref name="other"/> into the first set.
        /// If a field number exists in both sets, the values in <paramref name="other"/>
        /// will be appended to the values in this set.
        /// </summary>
        public static UnknownFieldSet MergeFrom(UnknownFieldSet unknownFields,
                                                UnknownFieldSet other)
        {
            if (other == null)
            {
                return unknownFields;
            }
            if (unknownFields == null)
            {
                unknownFields = new UnknownFieldSet();
            }
            unknownFields.MergeFrom(other);
            return unknownFields;
        }


        /// <summary>
        /// Adds a field to the unknown field set. If a field with the same
        /// number already exists, the two are merged.
        /// </summary>
        private UnknownFieldSet MergeField(int number, UnknownField field)
        {
            if (number == 0)
            {
                throw new ArgumentOutOfRangeException("number", "Zero is not a valid field number.");
            }
            if (HasField(number))
            {
                GetOrAddField(number).MergeFrom(field);
            }
            else
            {
                AddOrReplaceField(number, field);
            }
            return this;
        }

        /// <summary>
        /// Clone an unknown field set from <paramref name="other"/>.
        /// </summary>
        public static UnknownFieldSet Clone(UnknownFieldSet other)
        {
            if (other == null)
            {
                return null;
            }
            UnknownFieldSet unknownFields = new UnknownFieldSet();
            unknownFields.MergeFrom(other);
            return unknownFields;
        }
    }
}

