//===============================================================================
// Microsoft patterns & practices
// Web Service Software Factory
//===============================================================================
// Copyright  Microsoft Corporation.  All rights reserved.
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
// OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
// LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
// FITNESS FOR A PARTICULAR PURPOSE.
//===============================================================================
// The example companies, organizations, products, domain names,
// e-mail addresses, logos, people, places, and events depicted
// herein are fictitious.  No association with any real company,
// organization, product, domain name, email address, logo, person,
// places, or events is intended or should be inferred.
//===============================================================================

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel.Design;
using System.ComponentModel;
using Microsoft.VisualStudio.Shell.Design;
using Microsoft.Practices.RecipeFramework.Library;
using Microsoft.VisualStudio.Shell.Interop;
using System.Diagnostics;

namespace Microsoft.Practices.SoftwareFactories.ServiceFactory.Editors.Grid.Design
{
    /// <summary>
    /// A TypeList converter class.
    /// </summary>
	public class TypeListConverter : TypeConverter
	{
        /// <summary>
        /// Returns whether this object supports a standard set of values that can be picked from a list, using the specified context.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that provides a format context.</param>
        /// <returns>
        /// true if <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"></see> should be called to find a common set of values the object supports; otherwise, false.
        /// </returns>
		public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
		{
			return true;
		}

        /// <summary>
        /// Returns whether the collection of standard values returned from <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"></see> is an exclusive list of possible values, using the specified context.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that provides a format context.</param>
        /// <returns>
        /// true if the <see cref="T:System.ComponentModel.TypeConverter.StandardValuesCollection"></see> returned from <see cref="M:System.ComponentModel.TypeConverter.GetStandardValues"></see> is an exhaustive list of possible values; false if other values are possible.
        /// </returns>
		public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
		{
			return true;
		}

        /// <summary>
        /// Returns a collection of standard values for the data type this type converter is designed for when provided with a format context.
        /// </summary>
        /// <param name="context">An <see cref="T:System.ComponentModel.ITypeDescriptorContext"></see> that provides a format context that can be used to extract additional information about the environment from which this converter is invoked. This parameter or properties of this parameter can be null.</param>
        /// <returns>
        /// A <see cref="T:System.ComponentModel.TypeConverter.StandardValuesCollection"></see> that holds a standard set of valid values, or null if the data type does not support a standard set of values.
        /// </returns>
		public override TypeConverter.StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
		{
			DynamicTypeService typeService = (DynamicTypeService)context.GetService(typeof(DynamicTypeService));
			Debug.Assert(typeService != null, "No dynamic type service registered.");
			
			IVsHierarchy hier = DteHelper.GetCurrentSelection(context);
			Debug.Assert(hier != null, "No active hierarchy is selected.");

			ITypeDiscoveryService typeDiscovery = typeService.GetTypeDiscoveryService(hier);
			if (typeDiscovery != null)
			{
				List<string> types = new List<string>();
				foreach (Type type in typeDiscovery.GetTypes(typeof(object), false))
				{
					if (ShouldInclude(type))
					{
						types.Add(type.FullName);
					}
				}

				types.Sort(StringComparer.CurrentCulture);

				return new StandardValuesCollection(types);
			}
			else
			{
				return new StandardValuesCollection(new List<string>());
			}
		}

        /// <summary>
        /// Shoulds the include.
        /// </summary>
        /// <param name="candidate">The candidate.</param>
        /// <returns></returns>
		protected virtual bool ShouldInclude(Type candidate)
		{
			return true;
		}
	}
}
