using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
// ReSharper disable InconsistentNaming
namespace Barotrauma.LuaCs.Services;
public interface IAssemblyManagementService : IService
{
#region Public API
///
/// Called when an assembly is loaded.
///
public event Action OnAssemblyLoaded;
///
/// Called when an assembly is marked for unloading, before unloading begins. You should use this to cleanup
/// any references that you have to this assembly.
///
public event Action OnAssemblyUnloading;
///
/// Called whenever an exception is thrown. First arg is a formatted message, Second arg is the Exception.
///
public event Action OnException;
///
/// For unloading issue debugging. Called whenever MemoryFileAssemblyContextLoader [load context] is unloaded.
///
// ReSharper disable once InconsistentNaming
public event Action OnACLUnload;
///
/// [DEBUG ONLY]
/// Returns a list of the current unloading ACLs.
///
// ReSharper disable once InconsistentNaming
public ImmutableList> StillUnloadingACLs { get; }
// ReSharper disable once MemberCanBePrivate.Global
///
/// Checks if there are any AssemblyLoadContexts still in the process of unloading.
///
public bool IsCurrentlyUnloading { get; }
///
/// Allows iteration over all non-interface types in all loaded assemblies in the AsmMgr that are assignable to the given type (IsAssignableFrom).
/// Warning: care should be used when using this method in hot paths as performance may be affected.
///
/// The type to compare against
/// Forces caches to clear and for the lists of types to be rebuilt.
/// An Enumerator for matching types.
public IEnumerable GetSubTypesInLoadedAssemblies(bool rebuildList);
///
/// Tries to get types assignable to type from the ACL given the Guid.
///
///
///
///
/// Operation success.
public bool TryGetSubTypesFromACL(Guid id, out IEnumerable types);
///
/// Tries to get types from the ACL given the Guid.
///
///
///
///
public bool TryGetSubTypesFromACL(Guid id, out IEnumerable types);
///
/// Allows iteration over all types, including interfaces, in all loaded assemblies in the AsmMgr who's names match the string.
/// Note: Will return the by-reference equivalent type if the type name is prefixed with "out " or "ref ".
///
/// The string name of the type to search for.
/// An Enumerator for matching types. List will be empty if bad params are supplied.
public IEnumerable GetTypesByName(string typeName);
///
/// Allows iteration over all types (including interfaces) in all loaded assemblies managed by the AsmMgr.
/// Warning: High usage may result in performance issues.
///
/// An Enumerator for iteration.
public IEnumerable GetAllTypesInLoadedAssemblies();
///
/// Returns a list of all loaded ACLs.
/// WARNING: References to these ACLs outside the AssemblyManager should be kept in a WeakReference in order
/// to avoid causing issues with unloading/disposal.
///
///
public IEnumerable GetAllLoadedACLs();
#endregion
#region InternalAPI
/*** Notes: Internal API uses the 'public' modifier because of the common and recommended use of publicized APIs
* by third-party add-ins.
*/
///
/// [Unsafe] Warning: only for use in nested threading functions. Requires care to manage access.
/// Does not make any guarantees about the state of the ACL after the list has been returned.
///
///
public ImmutableList UnsafeGetAllLoadedACLs();
///
/// Used by content package and plugin management to stop unloading of a given ACL until all plugins have gracefully closed.
///
public event System.Func IsReadyToUnloadACL;
///
/// Compiles an assembly from supplied references and syntax trees into the specified AssemblyContextLoader.
/// A new ACL will be created if the Guid supplied is Guid.Empty.
///
///
///
///
///
/// A non-unique name for later reference. Optional, set to null if unused.
/// The guid of the assembly
///
///
public AssemblyLoadingSuccessState LoadAssemblyFromMemory([NotNull] string compiledAssemblyName,
[NotNull] IEnumerable syntaxTree,
IEnumerable externalMetadataReferences,
[NotNull] CSharpCompilationOptions compilationOptions,
string friendlyName,
ref Guid id,
IEnumerable externFileAssemblyRefs = null);
///
/// Switches the ACL with the given Guid to Template Mode, which disables assembly name resolution for any assemblies loaded in it.
/// These ACLs are intended to be used to host Assemblies for information only and not for code execution.
/// WARNING: This process is irreversible.
///
/// Guid of the ACL.
/// Whether an ACL was found with the given ID.
public bool SetACLToTemplateMode(Guid guid);
///
/// Tries to load all assemblies at the supplied file paths list into the ACl with the given Guid.
/// If the supplied Guid is Empty, then a new ACl will be created and the Guid will be assigned to it.
///
/// List of assemblies to try and load.
/// A non-unique name for later reference. Optional.
/// Guid of the ACL or Empty if none specified. Guid of ACL will be assigned to this var.
/// Operation success messages.
///
public AssemblyLoadingSuccessState LoadAssembliesFromLocations([NotNull] IEnumerable filePaths,
string friendlyName, ref Guid id);
///
/// Tries to begin the disposal process of ACLs.
///
/// Returns whether the unloading process could be initiated.
public bool TryBeginDispose();
///
/// Returns whether unloading is completed and updates the styate of the unloading cache.
///
///
public bool FinalizeDispose();
///
/// Tries to retrieve the LoadedACL with the given ID or null if none is found.
/// WARNING: External references to this ACL with long lifespans should be kept in a WeakReference
/// to avoid causing unloading/disposal issues.
///
/// GUID of the ACL.
/// The found ACL or null if none was found.
/// Whether an ACL was found.
public bool TryGetACL(Guid id, out AssemblyManager.LoadedACL acl);
#endregion
}