using System;
using System.Collections.Generic;

using BS.Shared.DataContracts;

namespace BeWo.Core
{
    public abstract class AbstractSorter
    {
        public enum SortDirection
        {
            Ascending, 
            Descending
        }

        public abstract List<SortItem> SortItems { get; }

        // abstract public Comparison<T> GetComparison(SortItem item);
        public virtual Comparison<IFilterableDC> GetComparison(string sortProperty, SortDirection direction)
        {
            return this.GetComparison(new SortItem(sortProperty, sortProperty), direction);
        }

        public virtual Comparison<IFilterableDC> GetComparison(SortItem item, SortDirection direction)
        {
            return (x, y) =>
                {
                    int mult = direction == SortDirection.Ascending ? 1 : -1;

                    object xValue = GetPropertyValue(x, item.Property);
                    object yValue = GetPropertyValue(y, item.Property);

                    if (xValue != null && yValue != null)
                    {
						if (xValue is DateTime && yValue is DateTime)
                        {
                            DateTime? xValueDT = xValue as DateTime?;
                            DateTime? yValueDT = yValue as DateTime?;

                            return mult * xValueDT.Value.CompareTo(yValueDT.Value);
                        }
                        else
                        {
							if (item.Property == "PersonnelNumber") //HACK
							{
								int xint = 0;
								int yint = 0;
								if (Int32.TryParse(xValue.ToString(), out xint) && Int32.TryParse(yValue.ToString(), out yint))
								{
									return mult * xint.CompareTo(yint);
								}
							}
							
                            return mult * xValue.ToString().CompareTo(yValue.ToString());
                        }
                    }
                    else if (xValue != null || yValue != null)
                    {
                        if (xValue != null)
                            return mult*xValue.ToString().CompareTo("");
                        else
                            return mult * "".CompareTo(yValue.ToString());
                    }
                    return 0;
                };
        }

        private object GetPropertyValue(object obj, String propertyName)
        {
            var prop = obj.GetType().GetProperty(propertyName);
            if (prop != null)
            {
                return prop.GetValue(obj, null);
            }
            var field = obj.GetType().GetField(propertyName);
            if (field != null)
                return field.GetValue(obj);
            return null;
        }
    }
}