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

using System.Resources;

namespace System;

internal static partial class SR
{
    private static readonly bool s_usingResourceKeys =
        AppContext.TryGetSwitch("System.Resources.UseSystemResourceKeys", out bool usingResourceKeys) && usingResourceKeys;

    // This method is used to decide if we need to append the exception message parameters to the message when calling SR.Format.
    // by default it returns the value of System.Resources.UseSystemResourceKeys AppContext switch or false if not specified.
    // Native code generators can replace the value this returns based on user input at the time of native code generation.
    // The Linker is also capable of replacing the value of this method when the application is being trimmed.
    internal static bool UsingResourceKeys() => s_usingResourceKeys;

    internal static string GetResourceString(string resourceKey)
    {
        if (UsingResourceKeys())
        {
            return resourceKey;
        }

        string? resourceString = null;
        try
        {
            resourceString =
#if SYSTEM_PRIVATE_CORELIB || NATIVEAOT
                InternalGetResourceString(resourceKey);
#else
                ResourceManager.GetString(resourceKey);
#endif
        }
        catch (MissingManifestResourceException) { }

        return resourceString!; // only null if missing resources
    }

    internal static string GetResourceString(string resourceKey, string defaultString)
    {
        string resourceString = GetResourceString(resourceKey);

        return resourceKey == resourceString || resourceString is null ? defaultString : resourceString;
    }

    internal static string Format(string resourceFormat, object? p1) =>
        UsingResourceKeys()
            ? string.Join(", ", resourceFormat, p1)
            : string.Format(resourceFormat, p1);

    internal static string Format(string resourceFormat, object? p1, object? p2) =>
        UsingResourceKeys()
            ? string.Join(", ", resourceFormat, p1, p2)
        : string.Format(resourceFormat, p1, p2);

    internal static string Format(string resourceFormat, object? p1, object? p2, object? p3) =>
        UsingResourceKeys()
        ? string.Join(", ", resourceFormat, p1, p2, p3)
        : string.Format(resourceFormat, p1, p2, p3);

    internal static string Format(string resourceFormat, params object?[]? args) =>
        args is not null
            ? UsingResourceKeys() ? $"{resourceFormat}, {string.Join(", ", args)}" : string.Format(resourceFormat, args)
            : resourceFormat;

    internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1) =>
        UsingResourceKeys()
            ? string.Join(", ", resourceFormat, p1)
            : string.Format(provider, resourceFormat, p1);

    internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2) =>
        UsingResourceKeys()
            ? string.Join(", ", resourceFormat, p1, p2)
            : string.Format(provider, resourceFormat, p1, p2);

    internal static string Format(IFormatProvider? provider, string resourceFormat, object? p1, object? p2, object? p3) =>
        UsingResourceKeys()
            ? string.Join(", ", resourceFormat, p1, p2, p3)
            : string.Format(provider, resourceFormat, p1, p2, p3);

    internal static string Format(IFormatProvider? provider, string resourceFormat, params object?[]? args) =>
        args is not null
            ? UsingResourceKeys()
                ? $"{resourceFormat}, {string.Join(", ", args)}"
                : string.Format(provider, resourceFormat, args)
            : resourceFormat;
}
