// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

#if NETFRAMEWORK
using System.Security;
#endif

using Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.ObjectModel;
using Microsoft.VisualStudio.TestPlatform.MSTestAdapter.PlatformServices.Interface;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Microsoft.VisualStudio.TestPlatform.MSTest.TestAdapter.Execution;

internal sealed class TestAssemblySettingsProvider
#if NETFRAMEWORK
    : MarshalByRefObject
#endif
{
#if NETFRAMEWORK
    /// <summary>
    /// Returns object to be used for controlling lifetime, null means infinite lifetime.
    /// </summary>
    /// <returns>
    /// The <see cref="object"/>.
    /// </returns>
    [SecurityCritical]
    public override object? InitializeLifetimeService() => null;
#endif

    [SuppressMessage(
        "Performance",
        "CA1822:Mark members as static",
        Justification = "Intentionally not static. We call it from a different AppDomain")]
    internal TestAssemblySettings GetSettings(string source)
    {
        var testAssemblySettings = new TestAssemblySettings();

        // Load the source.
        Assembly testAssembly = PlatformServiceProvider.Instance.FileOperations.LoadAssembly(source);

        IReflectionOperations reflectionOperations = PlatformServiceProvider.Instance.ReflectionOperations;
        ParallelizeAttribute? parallelizeAttribute = reflectionOperations.GetSingleAttributeOrDefault<ParallelizeAttribute>(testAssembly);

        if (parallelizeAttribute is not null)
        {
            testAssemblySettings.Workers = parallelizeAttribute.Workers;
            testAssemblySettings.Scope = parallelizeAttribute.Scope;

            if (testAssemblySettings.Workers == 0)
            {
                testAssemblySettings.Workers = Environment.ProcessorCount;
            }
        }

        testAssemblySettings.CanParallelizeAssembly = !reflectionOperations.IsAttributeDefined<DoNotParallelizeAttribute>(testAssembly);

        return testAssemblySettings;
    }
}
