using System;

using IllusionInjector;
using IllusionPlugin;

namespace GamecraftModdingAPI.Utility
{
    /// <summary>
    /// Simple plugin interaction operations
    /// </summary>
    public static class Dependency
    {
        /// <summary>
        /// Find a plugin by name
        /// </summary>
        /// <returns>The plugin.</returns>
        /// <param name="name">The plugin's name.</param>
        public static IPlugin GetPlugin(string name)
		{
			foreach(IPlugin plugin in PluginManager.Plugins)
			{
                if (plugin.Name == name)
				{
					return plugin;
				}
			}
			return null;
		}

        /// <summary>
        /// Gets the plugin version.
		/// This gives priority to the plugin's Version string but falls back to the Assembly's version
        /// </summary>
        /// <returns>The plugin's version.</returns>
        /// <param name="name">The plugin's name.</param>
        public static Version GetPluginVersion(string name)
		{
			IPlugin plugin = GetPlugin(name);
			if (plugin != null) {
				try
				{
					return new Version(plugin.Version);
				} catch (Exception e) when (
				    e is ArgumentException
					|| e is ArgumentNullException
				    || e is ArgumentOutOfRangeException
					|| e is FormatException
				    || e is OverflowException) {}
				return plugin.GetType().Assembly.GetName().Version;
			}
			return null;
		}
        
        // (I'm leaving the auto-generated version)
        // <summary>
        // Hell the specified name and version.
        // </summary>
        // <returns>The hell.</returns>
        // <param name="name">Name.</param>
        // <param name="version">Version.</param>
        /// <summary>
        /// Detect if you're in dependency hell with respect to the plugin.
		/// ie Check if the plugin doesn't exist or is out of date.
		/// When version is null, this only checks if the plugin exists.
		/// The version is retrieved using GetPluginVersion(string name).
        /// </summary>
        /// <returns>Are you in dependency hell?</returns>
        /// <param name="name">The plugin's name'</param>
        /// <param name="version">The target version.</param>
		public static bool Hell(string name, Version version = null)
		{
			Version pluginVersion = GetPluginVersion(name);
			if (version == null) {
				return pluginVersion == null;
			}
			return (pluginVersion == null || pluginVersion < version);
		}
    }
}