using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.Loader;

namespace ExtensiblePortfolioSite.SDK.Plugins
{
    internal sealed class Library : IPluginManagedLibrary
    {
        private class LibraryLoadContext : AssemblyLoadContext
        {
            private readonly Library Library;

            public LibraryLoadContext(Library Library) : base(true) => this.Library = Library;

            protected override IntPtr LoadUnmanagedDll(string unmanagedDllName)
            {
                IPluginUnmanagedLibrary? Lib = PluginManager.LoadUnmanagedLibrary(unmanagedDllName);
                if (Lib == null)
                    return IntPtr.Zero;

                Library.References.Add(Lib);
                return Lib.LibraryPtr;
            }
            protected override Assembly? Load(AssemblyName assemblyName)
            {
                IPluginManagedLibrary? Lib = PluginManager.LoadLibrary(assemblyName);
                if (Lib == null)
                    return PluginManager.GetFixedAssembly(assemblyName);

                Library.References.Add(Lib);
                return Lib.Assembly;
            }
        }

        public String Location { get; }
        public Assembly Assembly { get; }

        public IList<IPluginLibrary> Dependents { get; } = new List<IPluginLibrary>();
        IReadOnlyList<IPluginLibrary> IPluginLibrary.References => References.AsReadOnly();
        private List<IPluginLibrary> References = new();


        private readonly LibraryLoadContext LoadContext;
        public Library(String Location)
        {
            this.Location = Location;
            this.LoadContext = new LibraryLoadContext(this);
            this.Assembly = this.LoadContext.LoadFromAssemblyPath(Location);
        }

        public void Disposing() => this.LoadContext.Unload();
    }
}
