using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ModuleManager.UnitTests
{
    public class ExclusiveModuleManagerTests : UnitTestSharp.TestFixture
    {
        interface INothingModule : IExclusiveModule
        {
            int Loaded { get; set; }
            int Unloaded { get; set; }
        }

        public class Nothing : INothingModule
        {
            public int Loaded { get; set; }
            public int Unloaded { get; set; }

            public void Load() { Loaded++; }
            public void Unload() { Unloaded++; }
        }

        public class Nothing2 : INothingModule
        {
            public int Loaded { get; set; }
            public int Unloaded { get; set; }

            public void Load() { Loaded++; }
            public void Unload() { Unloaded++; }
        }

        public class SetCurrentModule : UnitTestSharp.TestFixture
        {
            public void Works()
            {
                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                manager.SetCurrentModule(manager.Modules.First());

                CheckEqual(typeof(Nothing), manager.CurrentModule.GetType());
                CheckNotEqual(null, manager.CurrentModule);
            }

            public void Bogus()
            {
                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                CheckThrow(typeof(Exception));

                manager.SetCurrentModule("Your mom");
            }

            public void NotifiedOnChange()
            {
                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                manager.SetCurrentModule(manager.Modules.First());
                CheckEqual(1, manager.CurrentModule.Loaded);
                CheckEqual(0, manager.CurrentModule.Unloaded);
            }

            public void SettingToSame()
            {
                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                manager.SetCurrentModule(manager.Modules.First());
                manager.SetCurrentModule(manager.Modules.First());

                CheckEqual(2, manager.CurrentModule.Loaded);
                CheckEqual(1, manager.CurrentModule.Unloaded);
            }

            public void PingPong()
            {
                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                manager.SetCurrentModule(manager.Modules[0]);
                manager.SetCurrentModule(manager.Modules[1]);
                manager.SetCurrentModule(manager.Modules[0]);

                CheckEqual(2, manager.CurrentModule.Loaded);
                CheckEqual(1, manager.CurrentModule.Unloaded);
            }
        }

        public class Listeners : UnitTestSharp.TestFixture
        {
            public void Fire()
            {
                TODO("Break into smaller tests.");

                var manager = new ExclusiveModuleManager<INothingModule>();

                manager.ExtractModulesFromAssembly(System.Reflection.Assembly.GetExecutingAssembly());

                int changing = 0;
                int changed = 0;
                
                manager.CurrentModuleChanging += delegate(IExclusiveModule module)
                {
                    changing++;

                    if (module != null)
                    {                        
                        CheckEqual(1, ((INothingModule)module).Loaded);
                        CheckEqual(0, ((INothingModule)module).Unloaded);
                    }
                };

                manager.CurrentModuleChanged += delegate(IExclusiveModule module)
                {
                    changed++;

                    if (module != null)
                    {
                        CheckEqual(1, ((INothingModule)module).Loaded);
                        CheckEqual(0, ((INothingModule)module).Unloaded);
                    }
                };

                manager.SetCurrentModule(manager.Modules.First());
                manager.SetCurrentModule(manager.Modules[1]);

                CheckEqual(2, changing);
                CheckEqual(2, changed);
            }
        }
    }
}