#region Copyright notice and license
// Protocol Buffers - Google's data interchange format
// Copyright 2008 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.Text;
using System.Text.RegularExpressions;

namespace Google.Protobuf.Reflection
{
    /// <summary>
    /// Contains lookup tables containing all the descriptors defined in a particular file.
    /// </summary>
    internal sealed class DescriptorPool
    {
        private readonly IDictionary<string, IDescriptor> descriptorsByName =
            new Dictionary<string, IDescriptor>();

        private readonly IDictionary<ObjectIntPair<IDescriptor>, FieldDescriptor> fieldsByNumber =
            new Dictionary<ObjectIntPair<IDescriptor>, FieldDescriptor>();

        private readonly IDictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor> enumValuesByNumber =
            new Dictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor>();

        private readonly HashSet<FileDescriptor> dependencies = new HashSet<FileDescriptor>();

        internal DescriptorPool(IEnumerable<FileDescriptor> dependencyFiles)
        {
            foreach (FileDescriptor dependencyFile in dependencyFiles)
            {
                dependencies.Add(dependencyFile);
                ImportPublicDependencies(dependencyFile);
            }

            foreach (FileDescriptor dependency in dependencyFiles)
            {
                AddPackage(dependency.Package, dependency);
            }
        }

        private void ImportPublicDependencies(FileDescriptor file)
        {
            foreach (FileDescriptor dependency in file.PublicDependencies)
            {
                if (dependencies.Add(dependency))
                {
                    ImportPublicDependencies(dependency);
                }
            }
        }

        /// <summary>
        /// Finds a symbol of the given name within the pool.
        /// </summary>
        /// <typeparam name="T">The type of symbol to look for</typeparam>
        /// <param name="fullName">Fully-qualified name to look up</param>
        /// <returns>The symbol with the given name and type,
        /// or null if the symbol doesn't exist or has the wrong type</returns>
        internal T FindSymbol<T>(string fullName) where T : class
        {
            descriptorsByName.TryGetValue(fullName, out IDescriptor result);
            if (result is T descriptor)
            {
                return descriptor;
            }

            // dependencies contains direct dependencies and any *public* dependencies
            // of those dependencies (transitively)... so we don't need to recurse here.
            foreach (FileDescriptor dependency in dependencies)
            {
                dependency.DescriptorPool.descriptorsByName.TryGetValue(fullName, out result);
                descriptor = result as T;
                if (descriptor != null)
                {
                    return descriptor;
                }
            }

            return null;
        }

        /// <summary>
        /// Adds a package to the symbol tables. If a package by the same name
        /// already exists, that is fine, but if some other kind of symbol
        /// exists under the same name, an exception is thrown. If the package
        /// has multiple components, this also adds the parent package(s).
        /// </summary>
        internal void AddPackage(string fullName, FileDescriptor file)
        {
            int dotpos = fullName.LastIndexOf('.');
            String name;
            if (dotpos != -1)
            {
                AddPackage(fullName.Substring(0, dotpos), file);
                name = fullName.Substring(dotpos + 1);
            }
            else
            {
                name = fullName;
            }

            if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
            {
                if (old is not PackageDescriptor)
                {
                    throw new DescriptorValidationException(file,
                                                            "\"" + name +
                                                            "\" is already defined (as something other than a " +
                                                            "package) in file \"" + old.File.Name + "\".");
                }
            }
            descriptorsByName[fullName] = new PackageDescriptor(name, fullName, file);
        }

        /// <summary>
        /// Adds a symbol to the symbol table.
        /// </summary>
        /// <exception cref="DescriptorValidationException">The symbol already existed
        /// in the symbol table.</exception>
        internal void AddSymbol(IDescriptor descriptor)
        {
            ValidateSymbolName(descriptor);
            string fullName = descriptor.FullName;

            if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
            {
                int dotPos = fullName.LastIndexOf('.');
                string message;
                if (descriptor.File == old.File)
                {
                    if (dotPos == -1)
                    {
                        message = "\"" + fullName + "\" is already defined.";
                    }
                    else
                    {
                        message = "\"" + fullName.Substring(dotPos + 1) + "\" is already defined in \"" +
                                  fullName.Substring(0, dotPos) + "\".";
                    }
                }
                else
                {
                    message = "\"" + fullName + "\" is already defined in file \"" + old.File.Name + "\".";
                }
                throw new DescriptorValidationException(descriptor, message);
            }
            descriptorsByName[fullName] = descriptor;
        }

        private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", FrameworkPortability.CompiledRegexWhereAvailable);

        /// <summary>
        /// Verifies that the descriptor's name is valid (i.e. it contains
        /// only letters, digits and underscores, and does not start with a digit).
        /// </summary>
        /// <param name="descriptor"></param>
        private static void ValidateSymbolName(IDescriptor descriptor)
        {
            if (descriptor.Name.Length == 0)
            {
                throw new DescriptorValidationException(descriptor, "Missing name.");
            }
            if (!ValidationRegex.IsMatch(descriptor.Name))
            {
                throw new DescriptorValidationException(descriptor,
                                                        "\"" + descriptor.Name + "\" is not a valid identifier.");
            }
        }

        /// <summary>
        /// Returns the field with the given number in the given descriptor,
        /// or null if it can't be found.
        /// </summary>
        internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number)
        {
            fieldsByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(messageDescriptor, number), out FieldDescriptor ret);
            return ret;
        }

        internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number)
        {
            enumValuesByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(enumDescriptor, number), out EnumValueDescriptor ret);
            return ret;
        }

        /// <summary>
        /// Adds a field to the fieldsByNumber table.
        /// </summary>
        /// <exception cref="DescriptorValidationException">A field with the same
        /// containing type and number already exists.</exception>
        internal void AddFieldByNumber(FieldDescriptor field)
        {
            // for extensions, we use the extended type, otherwise we use the containing type
            ObjectIntPair<IDescriptor> key = new ObjectIntPair<IDescriptor>(field.Proto.HasExtendee ? field.ExtendeeType : field.ContainingType, field.FieldNumber);
            if (fieldsByNumber.TryGetValue(key, out FieldDescriptor old))
            {
                throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
                                                               "has already been used in \"" +
                                                               field.ContainingType.FullName +
                                                               "\" by field \"" + old.Name + "\".");
            }
            fieldsByNumber[key] = field;
        }

        /// <summary>
        /// Adds an enum value to the enumValuesByNumber table. If an enum value
        /// with the same type and number already exists, this method does nothing.
        /// (This is allowed; the first value defined with the number takes precedence.)
        /// </summary>
        internal void AddEnumValueByNumber(EnumValueDescriptor enumValue)
        {
            ObjectIntPair<IDescriptor> key = new ObjectIntPair<IDescriptor>(enumValue.EnumDescriptor, enumValue.Number);
            if (!enumValuesByNumber.ContainsKey(key))
            {
                enumValuesByNumber[key] = enumValue;
            }
        }

        /// <summary>
        /// Looks up a descriptor by name, relative to some other descriptor.
        /// The name may be fully-qualified (with a leading '.'), partially-qualified,
        /// or unqualified. C++-like name lookup semantics are used to search for the
        /// matching descriptor.
        /// </summary>
        /// <remarks>
        /// This isn't heavily optimized, but it's only used during cross linking anyway.
        /// If it starts being used more widely, we should look at performance more carefully.
        /// </remarks>
        internal IDescriptor LookupSymbol(string name, IDescriptor relativeTo)
        {
            IDescriptor result;
            if (name.StartsWith("."))
            {
                // Fully-qualified name.
                result = FindSymbol<IDescriptor>(name.Substring(1));
            }
            else
            {
                // If "name" is a compound identifier, we want to search for the
                // first component of it, then search within it for the rest.
                int firstPartLength = name.IndexOf('.');
                string firstPart = firstPartLength == -1 ? name : name.Substring(0, firstPartLength);

                // We will search each parent scope of "relativeTo" looking for the
                // symbol.
                StringBuilder scopeToTry = new StringBuilder(relativeTo.FullName);

                while (true)
                {
                    // Chop off the last component of the scope.

                    int dotpos = scopeToTry.ToString().LastIndexOf(".");
                    if (dotpos == -1)
                    {
                        result = FindSymbol<IDescriptor>(name);
                        break;
                    }
                    else
                    {
                        scopeToTry.Length = dotpos + 1;

                        // Append firstPart and try to find.
                        scopeToTry.Append(firstPart);
                        result = FindSymbol<IDescriptor>(scopeToTry.ToString());

                        if (result != null)
                        {
                            if (firstPartLength != -1)
                            {
                                // We only found the first part of the symbol.  Now look for
                                // the whole thing.  If this fails, we *don't* want to keep
                                // searching parent scopes.
                                scopeToTry.Length = dotpos + 1;
                                scopeToTry.Append(name);
                                result = FindSymbol<IDescriptor>(scopeToTry.ToString());
                            }
                            break;
                        }

                        // Not found.  Remove the name so we can try again.
                        scopeToTry.Length = dotpos;
                    }
                }
            }

            if (result == null)
            {
                throw new DescriptorValidationException(relativeTo, "\"" + name + "\" is not defined.");
            }
            else
            {
                return result;
            }
        }
    }
}