using System;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using InABox.Core;
using JetBrains.Annotations;
using Syncfusion.SfDataGrid.XForms;
using Xamarin.Forms;

namespace InABox.Mobile
{

    public abstract class MobileGridColumn : IMobileGridColumn
    {
        
        [CanBeNull]
        public static IMobileGridColumn Create(Type entityType, String columnName)
        {
            var prop = CoreUtils.GetProperty(entityType, columnName);
            var baseType = CoreUtils.TypeList(
                new[] { typeof(MobileGridColumn).Assembly },
                x=>x.IsSubclassOf(typeof(MobileGridColumn)) 
                   && !x.IsAbstract 
                   && x.BaseType?.GenericTypeArguments.Contains(prop.PropertyType) == true
            ).FirstOrDefault();
            if (baseType != null)
            {
                var resultType = baseType.MakeGenericType(entityType);
                var result = (IMobileGridColumn)Activator.CreateInstance(resultType);
                result.ColumnName = columnName;
                return result;
            }
            return null;
        }

        public abstract Action<IMobileGridColumn, object> Tapped { get; set; }
        public abstract string ColumnName { get; set; }
        public abstract GridLength Width { get; set; }
        public abstract string Caption { get; set; }
        public abstract TextAlignment Alignment { get; set; }
        public abstract GridColumn CreateColumn();
    }
    
    public abstract class MobileGridColumn<TEntity, TType> : MobileGridColumn
    {

        private Expression<Func<TEntity,TType>> _column;
        public Expression<Func<TEntity, TType>> Column
        {
            get => _column;
            set
            {
                _column = value;
                _columnName = Column?.ToString().Replace(" ","").Replace("x=>x.","") ?? string.Empty;
            }
        }

        private String _columnName;
        public override String ColumnName
        {
            get => _columnName;
            set
            {
                _columnName = value;
                _column = CoreUtils.CreateLambdaExpression<TEntity, TType>(value);
            }
        }
        
        public override GridLength Width { get; set; } = GridLength.Star;

        public override String Caption { get; set; }
        
        public override TextAlignment Alignment { get; set; } = TextAlignment.Center;

        public override Action<IMobileGridColumn, object> Tapped { get; set; }
        
        protected virtual View HeaderContent()
        {
            var label = new Label()
            {
                Text = String.IsNullOrWhiteSpace(Caption) 
                    ? ColumnName
                    : Caption,
                Margin = new Thickness(2,0),
                FontSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label)),
                TextColor = Color.Black,
                VerticalTextAlignment = TextAlignment.Center,
                HorizontalTextAlignment = Alignment,
            };
            return label;
        }

        private class MobileGridColumnConverter : IValueConverter
        {

            private readonly Func<object,object> OnFormatValue;

            public MobileGridColumnConverter(Func<object,object> onformatvalue)
            {
                OnFormatValue = onformatvalue;
            }
            
            public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
            {
                return OnFormatValue?.Invoke(value);
            }

            public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
            {
                throw new NotImplementedException();
            }
        }
        
        public TColumn CreateColumn<TColumn>() where TColumn : GridColumn, new()
        {
            var result = new TColumn();
            
            result.MappingName = ColumnName;
            result.DisplayBinding =
                new Binding(ColumnName, BindingMode.OneWay, new MobileGridColumnConverter(FormatValue));
            
            if (Width.IsStar)
                result.ColumnSizer = ColumnSizer.Star;
            else if (Width.IsAuto)
                result.ColumnSizer = ColumnSizer.Auto;
            else
            {
                result.ColumnSizer = ColumnSizer.None;
                result.Width = Width.Value;
            }

            result.TextAlignment = Alignment;
            result.CellStyle.Setters.Add(new Setter() { Property = GridCell.ForegroundProperty, Value = Color.Black });
            
            result.HeaderTextAlignment = Alignment;
            result.HeaderText = Caption;
            result.Padding = 0;
            result.CellTextSize = Device.GetNamedSize(NamedSize.Micro, typeof(Label));
            
            result.HeaderTemplate = new DataTemplate(() =>
            {
                var layout = new Grid()
                {
                    VerticalOptions = LayoutOptions.Fill,
                    RowSpacing = 0,
                    ColumnSpacing = 0
                };
                
                layout.RowDefinitions.Add(new RowDefinition() { Height = GridLength.Star });
                layout.RowDefinitions.Add(new RowDefinition() { Height = 1 });
                
                var content = HeaderContent();
                content.SetValue(Grid.RowProperty,0);
                layout.Children.Add(content);
                
                var box = new BoxView()
                {
                    HeightRequest = 1, 
                    BackgroundColor = Color.LightGray,
                    Margin = 0
                };
                box.SetValue(Grid.RowProperty,1);
                layout.Children.Add(box);
                
                return layout;
            });

            return result;

        }

        protected virtual object FormatValue(object value)
        {
            return value;
        }
        

    }
}