using System;
using System.Diagnostics;
using System.Reflection;
using System.Xml;
using nft.ui.command;
using nft.framework;
using nft.framework.plugin;
using nft.util;

namespace nft.contributions.ui
{
	/// <summary>
	/// CtbCommandEntity の概要の説明です。
	/// </summary>
	public class CtbCommandEntity : Contribution
	{
		protected enum MethodType { Static, Instance, Constructor };
		protected readonly string commandType;
		protected readonly ICommandEntity_Old entity;
		protected readonly Type targetType;
		protected readonly MethodType methodType;
		protected readonly string methodName;
		private string path;

        public CtbCommandEntity(Plugin p, ParamsReader contrib)
            : base(p, contrib)
		{
			path = contrib.SourceURI;
            ParamsReader cls = contrib["class"];
			targetType = PluginUtil.loadTypeFromManifest(cls);

            ParamsReader mn = contrib["method"];
            ParamsReader cmd = contrib["command"];
            commandType = cmd["type"].InnerTextOr("entity");

			if(!mn.IsNull)
			{
				methodName = mn["name"].InnerText;
                if (bool.Parse(mn["static"].InnerTextOr("false")))
					methodType = MethodType.Static;
				else
					methodType = MethodType.Instance;

				if( methodName == null )
				{
					string templ = Main.resources["xml.attribute_not_found"].stringValue;
					throw new Exception(string.Format(templ,"method","name",contrib.SourceURI));
				}
			}
			else
				methodType = MethodType.Constructor;

			entity = CreateEntity(contrib);
			PluginUtil.RegisterCommand( id, entity, cmd );
		}

		protected virtual ICommandEntity_Old CreateEntity( ParamsReader contrib )
		{
			if( commandType.Equals("ModalForm"))
				return new ModalFormCommand(targetType);
			if( commandType.Equals("ModelessForm"))
				return new ModelessFormCommand(targetType);
            if (commandType.Equals("SubForm"))
				return new SubformCommand(contrib);
			ICommandEntity_Old entity = CreateTarget() as ICommandEntity_Old;
			if(entity==null)
			{
				string templ = Main.resources["plugin.invalid_command_entity"].stringValue;
				string[] args = new string[]{ commandType, targetType.Name, methodName };
				throw new PluginXmlException(contrib,string.Format(templ,args));
			}
			return entity;
		}

        public ICommandEntity_Old CommandEntity {
            get { return entity; }
        }

		public object CreateTarget()
		{
			try 
			{				
				if( methodType == MethodType.Static )
				{
					object obj = targetType.InvokeMember(methodName,
                        BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static,
						null,null,new object[]{id});
					return obj;
				}
				else
				{
					object obj = Activator.CreateInstance(targetType);
					if( methodType == MethodType.Instance )
						return targetType.InvokeMember(methodName,
							BindingFlags.Public|BindingFlags.InvokeMethod|BindingFlags.Instance,
							null,obj,new object[]{id});
					else 
						return obj; // MethodType.Constructor
				}
			} 
			catch( Exception e ) 
			{
				string templ = Main.resources["xml.class_load_error"].stringValue;
				throw new Exception(string.Format(templ,targetType.FullName,path),e);
			}			
		}
	}
}
