using System;
using System.Windows.Forms;
using nft.framework;
using nft.framework.plugin;
using System.Collections.Generic;

namespace nft.util
{
	/// <summary>
	/// ContribListControlHelper の概要の説明です。
	/// </summary>
	public class ContribListControlHelper
	{
		private ContribListControlHelper(){}

		public static int Set( ComboBox combo, string ctbType, bool hideDisabled, IListContribFilter filter )
		{
			IEnumerable<Contribution> en = GetArray( ctbType, hideDisabled );
			if( en == null ) return -1;
			int n = 0;
			foreach( Contribution c in en )
				if(filter.IsValid(c))
				{
					combo.Items.Add( new AbstractItem(c) );
					n++;
				}
			return n;
		}

		public static int Set( ComboBox combo, string ctbType, bool hideDisabled )
		{
			return Set( combo, ctbType, hideDisabled, defaultFilter );
		}


		public static Contribution GetContribution( ComboBox combo, int index )
		{
			if( index<0 || combo.Items.Count<index ) return null;
			AbstractItem item = combo.Items[index] as AbstractItem;
			if( item != null )
				return PluginManager.theInstance.GetContribution((VContributionId) item.ID);
			else
				return null;
		}

        public static void SelectContribution(ComboBox combo, Contribution ctb) {
            if (ctb != null) {
                SelectContribution(combo, ctb.ContributionID);
            } else {
                combo.SelectedIndex = -1;
            }
        }

        public static void SelectContribution(ComboBox combo, VContributionId ctbID) {
            if (ctbID != null) {
                for (int i = 0; i < combo.Items.Count; i++) {
                    AbstractItem item = combo.Items[i] as AbstractItem;
                    if (item != null && item.ID.Equals(ctbID)) {
                        combo.SelectedIndex = i;
                        break;
                    }
                }
                throw new ArgumentOutOfRangeException("This combobox does not contains the contribution id=" + ctbID);
            } else {
                combo.SelectedIndex = -1;
            }
        }

		private static IEnumerable<Contribution> GetArray( string ctbType, bool hideDisabled )
		{
			PluginManager pm = PluginManager.theInstance;
			Type t = pm.GetDefinedType(ctbType);
			if( t == null ) return null;
			return pm.EnumContributions(t,hideDisabled);
		}

		#region Default Filter
		static internal IListContribFilter defaultFilter = new DefaultFilter();

		class DefaultFilter : IListContribFilter
		{
			#region IListContribFilter メンバ
			public bool IsValid(Contribution contrib)
			{
				return true;
			}
			#endregion
		}

		#endregion

    }
    public class ContribListControlHelper<T> where T:Contribution {
        
        public int Set(ComboBox combo, bool hideDisabled, IListContribFilter filter) {
            int n = 0;
            foreach (T c in GetEnumerable(hideDisabled))
                if (filter.IsValid(c)) {
                    combo.Items.Add(new AbstractItem(c));
                    n++;
                }
            return n;
        }

        public int Set(ComboBox combo, bool hideDisabled) {
            return Set(combo, hideDisabled, ContribListControlHelper.defaultFilter);
        }


        public T GetContribution(ComboBox combo, int index) {
            if (index < 0 || combo.Items.Count < index) return null;
            AbstractItem item = combo.Items[index] as AbstractItem;
            if (item != null)
                return PluginManager.theInstance.GetContribution((VContributionId) item.ID) as T;
            else
                return null;
        }

        public void SelectContribution(ComboBox combo, T obj) {
            IHasNameAndID ctb = obj as IHasNameAndID;
            if (ctb != null) {
                SelectContribution(combo, ctb.ID.AsString);
            } else {
                combo.SelectedIndex = -1;
            }
        }

        public void SelectContribution(ComboBox combo, string ctbID) {
            if (ctbID != null) {
                for (int i = 0; i < combo.Items.Count; i++) {
                    AbstractItem item = combo.Items[i] as AbstractItem;
                    if (item != null && item.ID.Equals(ctbID)) {
                        combo.SelectedIndex = i;
                        break;
                    }
                }
                throw new ArgumentOutOfRangeException("This combobox does not contains the contribution id=" + ctbID);
            } else {
                combo.SelectedIndex = -1;
            }
        }

        private IEnumerable<T> GetEnumerable(bool hideDisabled) {
            PluginManager pm = PluginManager.theInstance;
            return pm.EnumContributions<T>(hideDisabled);
        }
    }

	public interface IListContribFilter
	{
		bool IsValid( Contribution contrib );									 
	}

		sealed class AbstractItem
		{
			public readonly string Name;
			public readonly IIdentifier ID;
			public AbstractItem( IHasNameAndID entity )
			{
				this.Name = entity.Name;
				this.ID = entity.ID;
			}
			public override string ToString()
			{
				return Name;
			}
		}
	}
