using System;
using Telerik.Windows.Controls;
using Telerik.Windows.Data;

namespace CustomFilterRow_WPF
{
	public class ColumnFilterCellFactory
	{
		public static ColumnFilterCell CreateColumnHeader(GridViewBoundColumnBase column)
		{
			ColumnFilterCell columnHeader = CreateColumnHeaderFromType(column.DataType);

			columnHeader.FilterDescriptor = new Telerik.Windows.Data.FilterDescriptor();
			columnHeader.FilterDescriptor.Member = column.DataMemberBinding.Path.Path;
			columnHeader.FilterDescriptor.Operator = FilterOperator.IsEqualTo;
			columnHeader.FilterDescriptor.MemberType = column.DataType;

			return columnHeader;
		}

		private static ColumnFilterCell CreateColumnHeaderFromType(Type type)
		{
			if ((type == typeof(bool?)) || (type == typeof(bool)))
			{
				return new BooleanColumnHeader();
			}

			if ((type == typeof(DateTime?)) || (type == typeof(DateTime)))
			{
				return new DateTimeColumnHeader();
			}

			if (IsNumeric(type))
			{
				return new NumericColumnHeader();
			}

			return new TextColumnHeader();
		}

		public static bool IsNumeric(Type type)
		{
			type = GetNonNullableType(type);

			if (!type.IsEnum)
			{
				switch (Type.GetTypeCode(type))
				{
					case TypeCode.Char:
					case TypeCode.SByte:
					case TypeCode.Byte:
					case TypeCode.Int16:
					case TypeCode.UInt16:
					case TypeCode.Int32:
					case TypeCode.UInt32:
					case TypeCode.Int64:
					case TypeCode.UInt64:
					case TypeCode.Single:
					case TypeCode.Double:
					case TypeCode.Decimal:
						return true;
				}
			}

			return false;
		}

		private static Type GetNonNullableType(Type type)
		{
			if (IsNullableType(type))
			{
				return Nullable.GetUnderlyingType(type);
			}

			return type;
		}

		private static bool IsNullableType(Type type)
		{
			return type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>));
		}
	}
}
