// <auto-generated/>

#nullable enable annotations
#nullable disable warnings

// Suppress warnings about [Obsolete] member usage in generated code.
#pragma warning disable CS0612, CS0618

namespace System.Runtime.CompilerServices
{
    using System;
    using System.CodeDom.Compiler;

    [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
    [AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
    file sealed class InterceptsLocationAttribute : Attribute
    {
        public InterceptsLocationAttribute(int version, string data)
        {
        }
    }
}

namespace Microsoft.Extensions.Configuration.Binder.SourceGeneration
{
    using Microsoft.Extensions.Configuration;
    using System;
    using System.CodeDom.Compiler;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
    using System.Runtime.CompilerServices;

    [GeneratedCode("Microsoft.Extensions.Configuration.Binder.SourceGeneration", "42.42.42.42")]
    file static class BindingExtensions
    {
        #region IConfiguration extensions.
        /// <summary>Attempts to bind the configuration instance to a new instance of type T.</summary>
        [InterceptsLocation(1, "2Ny1FTOTCAvRq9jRD2PynXQBAABzcmMtMC5jcw==")] // src-0.cs(13,17)
        public static T? Get<T>(this IConfiguration configuration) => (T?)(GetCore(configuration, typeof(T), configureOptions: null) ?? default(T));
        #endregion IConfiguration extensions.

        #region Core binding extensions.
        private readonly static Lazy<HashSet<string>> s_configKeys_ProgramMyClassWithCustomCollections = new(() => new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "CustomDictionary", "CustomList", "ICustomDictionary", "ICustomCollection", "IReadOnlyList", "UnsupportedIReadOnlyDictionaryUnsupported", "IReadOnlyDictionary", "CollectionStructExplicit" });

        public static object? GetCore(this IConfiguration configuration, Type type, Action<BinderOptions>? configureOptions)
        {
            ArgumentNullException.ThrowIfNull(configuration);

            BinderOptions? binderOptions = GetBinderOptions(configureOptions);

            if (!HasValueOrChildren(configuration))
            {
                return null;
            }

            if (type == typeof(global::Program.MyClassWithCustomCollections))
            {
                var instance = new global::Program.MyClassWithCustomCollections();
                BindCore(configuration, ref instance, defaultValueIfNotFound: true, binderOptions);
                return instance;
            }

            throw new NotSupportedException($"Unable to bind to type '{type}': generator did not detect the type as input.");
        }

        public static void BindCore(IConfiguration configuration, ref global::Program.CustomDictionary<string, int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            foreach (IConfigurationSection section in configuration.GetChildren())
            {
                if (TryGetConfigurationValue(section, key: null, out string? value))
                {
                    if (!string.IsNullOrEmpty(value))
                    {
                        instance[section.Key] = ParseInt(value, section.Path);
                    }
                }
            }
        }

        public static void BindCore(IConfiguration configuration, ref global::Program.CustomList instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            foreach (IConfigurationSection section in configuration.GetChildren())
            {
                if (TryGetConfigurationValue(section, key: null, out string? value))
                {
                    instance.Add(value);
                }
            }
        }

        public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyList<int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            if (instance is not ICollection<int> temp)
            {
                return;
            }

            foreach (IConfigurationSection section in configuration.GetChildren())
            {
                if (TryGetConfigurationValue(section, key: null, out string? value))
                {
                    if (!string.IsNullOrEmpty(value))
                    {
                        temp.Add(ParseInt(value, section.Path));
                    }
                }
            }
        }

        public static void BindCore(IConfiguration configuration, ref global::System.Collections.Generic.IReadOnlyDictionary<string, int> instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            if (instance is not IDictionary<string, int> temp)
            {
                return;
            }

            foreach (IConfigurationSection section in configuration.GetChildren())
            {
                if (TryGetConfigurationValue(section, key: null, out string? value))
                {
                    if (!string.IsNullOrEmpty(value))
                    {
                        temp[section.Key] = ParseInt(value, section.Path);
                    }
                }
            }
        }

        public static void BindCore(IConfiguration configuration, ref global::Program.CollectionStructExplicit instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            ICollection<string> temp = instance;

            foreach (IConfigurationSection section in configuration.GetChildren())
            {
                if (TryGetConfigurationValue(section, key: null, out string? value))
                {
                    temp.Add(value);
                }
            }
        }

        public static void BindCore(IConfiguration configuration, ref global::Program.MyClassWithCustomCollections instance, bool defaultValueIfNotFound, BinderOptions? binderOptions)
        {
            ValidateConfigurationKeys(typeof(global::Program.MyClassWithCustomCollections), s_configKeys_ProgramMyClassWithCustomCollections, configuration, binderOptions);

            var value1 = configuration.GetSection("CustomDictionary");
            if (AsConfigWithChildren(value1) is IConfigurationSection section2)
            {
                global::Program.CustomDictionary<string, int>? temp4 = instance.CustomDictionary;
                temp4 ??= new global::Program.CustomDictionary<string, int>();
                BindCore(section2, ref temp4, defaultValueIfNotFound: false, binderOptions);
                instance.CustomDictionary = temp4;
            }
            else
            {
                instance.CustomDictionary = instance.CustomDictionary;
            }

            var value5 = configuration.GetSection("CustomList");
            if (AsConfigWithChildren(value5) is IConfigurationSection section6)
            {
                global::Program.CustomList? temp8 = instance.CustomList;
                temp8 ??= new global::Program.CustomList();
                BindCore(section6, ref temp8, defaultValueIfNotFound: false, binderOptions);
                instance.CustomList = temp8;
            }
            else
            {
                instance.CustomList = instance.CustomList;
            }

            var value9 = configuration.GetSection("IReadOnlyList");
            if (AsConfigWithChildren(value9) is IConfigurationSection section10)
            {
                global::System.Collections.Generic.IReadOnlyList<int>? temp12 = instance.IReadOnlyList;
                temp12 = temp12 is null ? (global::System.Collections.Generic.IReadOnlyList<int>)new List<int>() : (global::System.Collections.Generic.IReadOnlyList<int>)new List<int>(temp12);
                BindCore(section10, ref temp12, defaultValueIfNotFound: false, binderOptions);
                instance.IReadOnlyList = temp12;
            }
            else
            {
                instance.IReadOnlyList = instance.IReadOnlyList;
            }

            var value13 = configuration.GetSection("IReadOnlyDictionary");
            if (AsConfigWithChildren(value13) is IConfigurationSection section14)
            {
                global::System.Collections.Generic.IReadOnlyDictionary<string, int>? temp16 = instance.IReadOnlyDictionary;
                temp16 = temp16 is null ? (global::System.Collections.Generic.IReadOnlyDictionary<string, int>)new Dictionary<string, int>() : (global::System.Collections.Generic.IReadOnlyDictionary<string, int>)temp16.ToDictionary(pair => pair.Key, pair => pair.Value);
                BindCore(section14, ref temp16, defaultValueIfNotFound: false, binderOptions);
                instance.IReadOnlyDictionary = temp16;
            }
            else
            {
                instance.IReadOnlyDictionary = instance.IReadOnlyDictionary;
            }

            var value17 = configuration.GetSection("CollectionStructExplicit");
            if (AsConfigWithChildren(value17) is IConfigurationSection section18)
            {
                global::Program.CollectionStructExplicit temp19 = instance.CollectionStructExplicit;
                var temp20 = new global::Program.CollectionStructExplicit();
                BindCore(section18, ref temp20, defaultValueIfNotFound: false, binderOptions);
                instance.CollectionStructExplicit = temp20;
                temp19 = temp20;
            }
            else
            {
                instance.CollectionStructExplicit = instance.CollectionStructExplicit;
            }
        }

        /// <summary>Tries to get the configuration value for the specified key.</summary>
        public static bool TryGetConfigurationValue(IConfiguration configuration, string key, out string? value)
        {
            if (configuration is ConfigurationSection section)
            {
                return section.TryGetValue(key, out value);
            }
        
            value = key != null ? configuration[key] : configuration is IConfigurationSection sec ? sec.Value : null;
            return value != null;
        }


        /// <summary>If required by the binder options, validates that there are no unknown keys in the input configuration object.</summary>
        public static void ValidateConfigurationKeys(Type type, Lazy<HashSet<string>> keys, IConfiguration configuration, BinderOptions? binderOptions)
        {
            if (binderOptions?.ErrorOnUnknownConfiguration is true)
            {
                List<string>? temp = null;
        
                foreach (IConfigurationSection section in configuration.GetChildren())
                {
                    if (!keys.Value.Contains(section.Key))
                    {
                        (temp ??= new List<string>()).Add($"'{section.Key}'");
                    }
                }
        
                if (temp is not null)
                {
                    throw new InvalidOperationException($"'ErrorOnUnknownConfiguration' was set on the provided BinderOptions, but the following properties were not found on the instance of {type}: {string.Join(", ", temp)}");
                }
            }
        }

        public static bool HasValueOrChildren(IConfiguration configuration)
        {
            if ((configuration as IConfigurationSection)?.Value is not null)
            {
                return true;
            }
            return AsConfigWithChildren(configuration) is not null;
        }

        public static IConfiguration? AsConfigWithChildren(IConfiguration configuration)
        {
            foreach (IConfigurationSection _ in configuration.GetChildren())
            {
                return configuration;
            }
            return null;
        }

        public static BinderOptions? GetBinderOptions(Action<BinderOptions>? configureOptions)
        {
            if (configureOptions is null)
            {
                return null;
            }
        
            BinderOptions binderOptions = new();
            configureOptions(binderOptions);
        
            if (binderOptions.BindNonPublicProperties)
            {
                throw new NotSupportedException($"The configuration binding source generator does not support 'BinderOptions.BindNonPublicProperties'.");
            }
        
            return binderOptions;
        }

        public static int ParseInt(string value, string? path)
        {
            try
            {
                return int.Parse(value, NumberStyles.Integer, CultureInfo.InvariantCulture);
            }
            catch (Exception exception)
            {
                throw new InvalidOperationException($"Failed to convert configuration value '{value ?? "null"}' at '{path}' to type '{typeof(int)}'.", exception);
            }
        }
        #endregion Core binding extensions.
    }
}
