using Microsoft.VisualStudio.TestTools.UnitTesting;
using System;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Text.Json;
using System.Threading;

namespace Shared
{

    public class UnitTesting
    {

        protected readonly IsEnvironment _IsEnvironment;

        public IsEnvironment IsEnvironment => _IsEnvironment;

        public UnitTesting(TestContext testContext, Type declaringType)
        {
            if (testContext is null || declaringType is null)
                _IsEnvironment = null;
            else
            {
                string projectDirectory = GetProjectDirectory(testContext);
                string json = JsonSerializer.Serialize(testContext.Properties);
                string vsCodeDirectory = Path.Combine(projectDirectory, ".vscode");
                if (!Directory.Exists(vsCodeDirectory))
                    Directory.CreateDirectory(vsCodeDirectory);
                string launchText = GetLaunchText();
                File.WriteAllText(Path.Combine(vsCodeDirectory, "launch.json"), launchText);
                for (int i = 0; i < int.MaxValue; i++)
                {
                    if (!json.Contains("Debugger.IsAttached") || Debugger.IsAttached)
                        break;
                    Thread.Sleep(500);
                }
                MethodBase methodBase = declaringType.GetMethod(testContext.TestName);
                if (!(methodBase is null))
                {
                    TestCategoryAttribute testCategoryAttribute = methodBase.GetCustomAttribute<TestCategoryAttribute>();
                    if (!(testCategoryAttribute is null))
                    {
                        foreach (string testCategory in testCategoryAttribute.TestCategories)
                            _IsEnvironment = new IsEnvironment(testCategory);
                    }
                }
                if (_IsEnvironment is null)
                    _IsEnvironment = new IsEnvironment(processesCount: null, nullASPNetCoreEnvironmentIsDevelopment: Debugger.IsAttached, nullASPNetCoreEnvironmentIsProduction: !Debugger.IsAttached);
            }
        }

        internal static string GetProjectDirectory(TestContext testContext)
        {
            string result;
            string[] checkFiles = null;
            result = Path.GetDirectoryName(testContext.DeploymentDirectory);
            for (int i = 0; i < int.MaxValue; i++)
            {
                if (string.IsNullOrEmpty(result))
                    break;
                checkFiles = Directory.GetFiles(result, "*.Tests.*proj", SearchOption.TopDirectoryOnly);
                if (checkFiles.Any())
                    break;
                result = Path.GetDirectoryName(result);
            }
            if (string.IsNullOrEmpty(result) || checkFiles is null || !checkFiles.Any())
                throw new Exception(result);
            return result;
        }

        internal static string GetLaunchText()
        {
            StringBuilder result = new StringBuilder();
            result.
                AppendLine("{").
                AppendLine("  \"configurations\": [").
                AppendLine("    {").
                AppendLine("      \"name\": \".NET Core Attach\",").
                AppendLine("      \"type\": \"coreclr\",").
                AppendLine("      \"request\": \"attach\",").
                AppendLine($"      \"processId\": {System.Diagnostics.Process.GetCurrentProcess().Id}").
                AppendLine("    }").
                AppendLine("  ]").
                AppendLine("}");
            return result.ToString();
        }

    }

}