using System.Reflection;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using skyscraper5.Skyscraper.Plugins;
using skyscraper8.UI.MonoGame.Bridge;

namespace skyscraper8.UI.MonoGame.Screenhacks
{
	internal class ScreenhackManager : GameObject
	{
		private Dictionary<int, ConstructorInfo> knownScreenhacks;

		public ScreenhackManager()
		{
			knownScreenhacks = new Dictionary<int, ConstructorInfo>();
			Assembly assembly = GetType().Assembly;
			Type screenhackBaseType = typeof(IScreenhack);
			Type pluginPriorityTYpe = typeof(PluginPriorityAttribute);
			Type[] types = assembly.GetTypes();
			foreach (Type type in types)
			{
				if (!type.IsAssignableTo(screenhackBaseType))
					continue;
				if (type.IsInterface)
					continue;
				ConstructorInfo constructor = type.GetConstructor(new Type[] { });
				Attribute attribute = type.GetCustomAttributes(pluginPriorityTYpe).FirstOrDefault();
				if (attribute == null)
				{
					throw new ScreenhackException(String.Format("{0} is missing the {1} attribute.", type.Name, nameof(PluginPriorityAttribute)));
				}

				PluginPriorityAttribute ppa = (PluginPriorityAttribute)attribute;
				knownScreenhacks.Add(ppa.Priority, constructor);
			}
		}

		private IScreenhack currentScreenhack;
		private int currentScreenhackId;

		public int WantedScreenhackId { get; set; }


		public void Update(GameTime gameTime, GraphicsDevice graphicsDevice)
		{
			if (currentScreenhack == null || currentScreenhackId != WantedScreenhackId)
			{
				ConstructorInfo constructorInfo = knownScreenhacks[WantedScreenhackId];
				object invoke = constructorInfo.Invoke(new object[] { });
				currentScreenhack = (IScreenhack)invoke;
				currentScreenhack.SetGraphicsDevice(graphicsDevice,graphicsDevice.PresentationParameters.Bounds);
				currentScreenhackId = WantedScreenhackId;
			}
		}

		public void Draw(GameTime gameTime, SpriteBatch spriteBatch, Rectangle windowBounds)
		{
			currentScreenhack.Draw(gameTime, spriteBatch, windowBounds);
		}
	}
}
