#if NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using FastReport.Code.CodeDom.Compiler;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace FastReport.Code.CSharp
{
    public class CSharpCodeProvider : CodeDomProvider
    {
        public override CompilerResults CompileAssemblyFromSource(CompilerParameters cp, string code)
        {
            DebugMessage(typeof(SyntaxTree).Assembly.FullName);

#if NET6_0_OR_GREATER
            DebugMessage($"{RuntimeInformation.RuntimeIdentifier} {RuntimeInformation.ProcessArchitecture} " +
                         $"{RuntimeInformation.OSArchitecture} {RuntimeInformation.OSDescription}");
#endif

            DebugMessage("FR.Compat: " +
#if NETSTANDARD
                "NETSTANDARD"
#elif NETCOREAPP
                         "NETCOREAPP"
#endif
            );

            var codeTree = CSharpSyntaxTree.ParseText(code);
            var options = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary,
                optimizationLevel: OptimizationLevel.Release,
                generalDiagnosticOption: ReportDiagnostic.Default,
                reportSuppressedDiagnostics: true);

            var references = new List<MetadataReference>();

            AddReferences(cp, references);

            DebugMessage($"References count: {references.Count}");
            //foreach (var reference in references)
            //    DebugMessage($"{reference.Display}");

            Compilation compilation = CSharpCompilation.Create(
                "_" + Guid.NewGuid().ToString("D"), new[] { codeTree },
                references, options
            );


            OnBeforeEmitCompilation(compilation);

            using (var ms = new MemoryStream())
            {
                DebugMessage("Emit...");
                var results = compilation.Emit(ms);
                if (results.Success)
                {
#if DEBUG
                    foreach (var d in results.Diagnostics)
                        if (d.Severity > DiagnosticSeverity.Hidden)
                            DebugMessage($"Compiler {d.Severity}: {d.GetMessage()}. Line: {d.Location}");
#endif

                    var compiledAssembly = Assembly.Load(ms.ToArray());
                    return new CompilerResults(compiledAssembly);
                }

                DebugMessage($"results not success, {ms.Length}");
                var result = new CompilerResults();
                foreach (var d in results.Diagnostics)
                    if (d.Severity == DiagnosticSeverity.Error)
                    {
                        var position = d.Location.GetLineSpan().StartLinePosition;
                        result.Errors.Add(new CompilerError
                        {
                            ErrorText = d.GetMessage(),
                            ErrorNumber = d.Id,
                            Line = position.Line,
                            Column = position.Character
                        });
                    }

                return result;
            }
        }

        public override void Dispose()
        {
        }
    }
}
#endif