using System;
using System.Linq;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;

namespace FooEditor
{
    class PluginManager<T> : IEnumerable<T>
    {
        [ImportMany]
        IEnumerable<Lazy<T>> plugins = null;

        public PluginManager(List<string> DontLoadList)
        {
            string GlobalPluginPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Plugin");

            var catalog = new AggregateCatalog();
            List<string> loadedList = new List<string>();
            AppendCatalogFromDirByAssembly(loadedList, catalog, Config.ApplicationFolder, "*.dll",DontLoadList);
            AppendCatalogFromDirByAssembly(loadedList, catalog, GlobalPluginPath, "*.dll",DontLoadList);
            CompositionContainer container = new CompositionContainer(catalog);
            container.ComposeParts(this);
        }

        public IEnumerator<T> GetEnumerator()
        {
            foreach (Lazy<T> plugin in this.plugins)
                yield return plugin.Value;
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        void AppendCatalogFromDirByAssembly(List<string> loadedAssemblies, AggregateCatalog catalog, string dir, string pattern, List<string> DontLoadList)
        {
            if (Directory.Exists(dir) == false)
                return;
            foreach (string path in System.IO.Directory.GetFiles(dir, pattern))
            {
                var ac = new AssemblyCatalog(path);
                string name = ac.Assembly.ManifestModule.Name;
                if (!loadedAssemblies.Contains(name))
                {
                    if (DontLoadList != null && DontLoadList.Contains(name))
                        continue;
                    catalog.Catalogs.Add(ac);
                    loadedAssemblies.Add(name);
                }
                else
                {
                    ac.Dispose();
                }
            }
        }
    }
}
