using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.Build.Locator;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.Text;

namespace Workspaces
{
	class Program
	{
		static async Task Main(string[] args)
		{
			var solutionPath = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), @"..\..\..\..\data\FirebirdSql.Data.FirebirdClient-7.1.1.0\Provider\src\NETProvider.sln");

			MSBuildLocator.RegisterMSBuildPath(@"C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\MSBuild\Current\Bin");

			// AdhocWorkspace
			using (var workspace = MSBuildWorkspace.Create())
			{
				workspace.WorkspaceFailed += (o, e) => Console.WriteLine(e.Diagnostic.Message);
				var solution = await workspace.OpenSolutionAsync(solutionPath);
				foreach (var project in solution.Projects)
				{
					foreach (var document in project.Documents)
					{
						var (result, name) = await AnalyzeDocument(document);
						if (!result)
						{
							Console.WriteLine($"{document.Name}: {name}");
						}
					}
				}
			}
		}

		static async Task<(bool, string)> AnalyzeDocument(Document document)
		{
			if (document.FilePath.EndsWith(@".cs", StringComparison.Ordinal))
			{
				var expectedFileName = Path.GetFileNameWithoutExtension(document.FilePath);
				var tree = await document.GetSyntaxTreeAsync();
				var root = await tree.GetRootAsync();
				foreach (var node in root.DescendantNodesAndSelf())
				{
					if (node is ClassDeclarationSyntax classDeclaration && !classDeclaration.Identifier.Text.Equals(expectedFileName, StringComparison.Ordinal))
					{
						return (false, classDeclaration.Identifier.Text);
					}
					if (node is StructDeclarationSyntax structDeclaration && !structDeclaration.Identifier.Text.Equals(expectedFileName, StringComparison.Ordinal))
					{
						return (false, structDeclaration.Identifier.Text);
					}
				}
			}
			return (true, null);
		}
	}
}
