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

using System;
using System.ComponentModel;
using System.Globalization;
using System.Reflection;
using System.Resources;
using System.Threading;

#nullable disable

namespace Microsoft.Build.Tasks
{
    [AttributeUsage(AttributeTargets.All)]
    internal sealed class SRDescriptionAttribute : DescriptionAttribute
    {
        private bool _replaced = false;

        /// <summary>
        ///     Constructs a new sys description.
        /// </summary>
        /// <param name='description'>
        ///     description text.
        /// </param>
        public SRDescriptionAttribute(string description) : base(description)
        {
        }

        /// <summary>
        ///     Retrieves the description text.
        /// </summary>
        /// <returns>
        ///     description
        /// </returns>
        public override string Description
        {
            get
            {
                if (!_replaced)
                {
                    _replaced = true;
                    DescriptionValue = SR.GetString(base.Description);
                }
                return base.Description;
            }
        }
    }

    [AttributeUsage(AttributeTargets.All)]
    internal sealed class SRCategoryAttribute : CategoryAttribute
    {
        public SRCategoryAttribute(string category) : base(category)
        {
        }

        protected override string GetLocalizedString(string value)
        {
            return SR.GetString(value);
        }
    }

    /// <summary>
    ///    AutoGenerated resource class. Usage:
    ///
    ///        string s = SR.GetString(SR.MyIdenfitier);
    /// </summary>
    internal sealed class SR
    {
        internal const string ClassDocComment = "ClassDocComment";
        internal const string ClassComments1 = "ClassComments1";
        internal const string ClassComments3 = "ClassComments3";
        internal const string StringPropertyComment = "StringPropertyComment";
        internal const string StringPropertyTruncatedComment = "StringPropertyTruncatedComment";
        internal const string NonStringPropertyComment = "NonStringPropertyComment";
        internal const string NonStringPropertyDetailedComment = "NonStringPropertyDetailedComment";
        internal const string CulturePropertyComment1 = "CulturePropertyComment1";
        internal const string CulturePropertyComment2 = "CulturePropertyComment2";
        internal const string ResMgrPropertyComment = "ResMgrPropertyComment";
        internal const string MismatchedResourceName = "MismatchedResourceName";
        internal const string InvalidIdentifier = "InvalidIdentifier";

        private static SR s_loader = null;
        private MainAssemblyFallbackResourceManager _resources;

        /// <summary>
        /// The containing assembly is set to lookup resources for the neutral language in satellite assemblies, not in the main assembly.
        /// System.Design resources are not meant to be translated, so the ResourceManager should not look for satellite assemblies.
        /// This ResourceManager forces resource lookup to be constrained to the current assembly and not look for satellites.
        /// </summary>
        private class MainAssemblyFallbackResourceManager : ResourceManager
        {
            public MainAssemblyFallbackResourceManager(string baseName, Assembly assembly) : base(baseName, assembly)
            {
                this.FallbackLocation = UltimateResourceFallbackLocation.MainAssembly;
            }
        }

        internal SR()
        {
            _resources = new MainAssemblyFallbackResourceManager("System.Design", this.GetType().Assembly);
        }

        private static SR GetLoader()
        {
            if (s_loader == null)
            {
                SR sr = new SR();
                Interlocked.CompareExchange(ref s_loader, sr, null);
            }
            return s_loader;
        }

        private static CultureInfo Culture
        {
            get { return null/*use ResourceManager default, CultureInfo.CurrentUICulture*/; }
        }

        public static ResourceManager Resources
        {
            get
            {
                return GetLoader()._resources;
            }
        }

        public static string GetString(string name, params object[] args)
        {
            SR sys = GetLoader();
            if (sys == null)
            {
                return null;
            }

            string res = sys._resources.GetString(name, SR.Culture);

            if (args?.Length > 0)
            {
                for (int i = 0; i < args.Length; i++)
                {
                    String value = args[i] as String;
                    if (value?.Length > 1024)
                    {
                        args[i] = value.Substring(0, 1024 - 3) + "...";
                    }
                }
                return String.Format(CultureInfo.CurrentCulture, res, args);
            }
            else
            {
                return res;
            }
        }

        public static string GetString(string name)
        {
            SR sys = GetLoader();
            if (sys == null)
            {
                return null;
            }

            return sys._resources.GetString(name, SR.Culture);
        }

        public static string GetString(string name, out bool usedFallback)
        {
            // always false for this version of gensr
            usedFallback = false;
            return GetString(name);
        }

        public static object GetObject(string name)
        {
            SR sys = GetLoader();
            if (sys == null)
            {
                return null;
            }

            return sys._resources.GetObject(name, SR.Culture);
        }
    }
}
