using Billing.Themes;
using Xamarin.Forms;

namespace Billing.UI
{

    public class OptionEntry : Entry { }
    public class OptionEditor : Editor { }

    public abstract class OptionCell : ViewCell
    {
        public static readonly BindableProperty TitleProperty = BindableProperty.Create(nameof(Title), typeof(string), typeof(OptionCell));
        public static readonly BindableProperty BackgroundColorProperty = BindableProperty.Create(nameof(BackgroundColor), typeof(Color), typeof(OptionCell));
        public static readonly BindableProperty IconProperty = BindableProperty.Create(nameof(Icon), typeof(ImageSource), typeof(OptionCell));

        public string Title
        {
            get => (string)GetValue(TitleProperty);
            set => SetValue(TitleProperty, value);
        }
        public Color BackgroundColor
        {
            get => (Color)GetValue(BackgroundColorProperty);
            set => SetValue(BackgroundColorProperty, value);
        }
        [TypeConverter(typeof(ImageSourceConverter))]
        public ImageSource Icon
        {
            get => (ImageSource)GetValue(IconProperty);
            set => SetValue(IconProperty, value);
        }

        protected abstract View Content { get; }

        public OptionCell()
        {
            View = new Grid
            {
                BindingContext = this,
                Padding = new Thickness(20, 0),
                ColumnDefinitions =
                {
                    new ColumnDefinition { Width = GridLength.Auto },
                    new ColumnDefinition { Width = new GridLength(.3, GridUnitType.Star) },
                    new ColumnDefinition { Width = new GridLength(.7, GridUnitType.Star) }
                },
                Children =
                {
                    new Image
                    {
                        WidthRequest = 20,
                        HeightRequest = 20,
                        Aspect = Aspect.AspectFit,
                        VerticalOptions = LayoutOptions.Center,
                        Margin = new Thickness(6, 0)
                    }
                    .Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter())
                    .Binding(Image.SourceProperty, nameof(Icon)),

                    new Label
                    {
                        LineBreakMode = LineBreakMode.TailTruncation,
                        VerticalOptions = LayoutOptions.Center
                    }
                    .GridColumn(1)
                    .Binding(Label.TextProperty, nameof(Title))
                    .DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),

                    Content.GridColumn(2)
                }
            }
            .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
        }
    }

    public abstract class OptionVerticalCell : OptionCell
    {
        public OptionVerticalCell()
        {
            View = new Grid
            {
                BindingContext = this,
                Padding = new Thickness(20, 0),
                ColumnDefinitions =
                {
                    new ColumnDefinition { Width = GridLength.Auto },
                    new ColumnDefinition { Width = GridLength.Star }
                },
                RowDefinitions =
                {
                    new RowDefinition { Height = new GridLength(40) },
                    new RowDefinition { Height = GridLength.Star }
                },
                Children =
                {
                    new Image
                    {
                        WidthRequest = 20,
                        HeightRequest = 20,
                        Aspect = Aspect.AspectFit,
                        VerticalOptions = LayoutOptions.Center,
                        Margin = new Thickness(6, 0)
                    }
                    .Binding(VisualElement.IsVisibleProperty, nameof(Icon), converter: new NotNullConverter())
                    .Binding(Image.SourceProperty, nameof(Icon)),

                    new Label
                    {
                        LineBreakMode = LineBreakMode.TailTruncation,
                        VerticalOptions = LayoutOptions.Center
                    }
                    .GridColumn(1)
                    .Binding(Label.TextProperty, nameof(Title))
                    .DynamicResource(Label.TextColorProperty, BaseTheme.TextColor),

                    Content.GridRow(1).GridColumnSpan(2)
                }
            }
            .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
        }
    }

    public class OptionTextCell : OptionCell
    {
        public static readonly BindableProperty DetailProperty = BindableProperty.Create(nameof(Detail), typeof(string), typeof(OptionTextCell));

        public string Detail
        {
            get => (string)GetValue(DetailProperty);
            set => SetValue(DetailProperty, value);
        }

        protected override View Content => new Label
        {
            HorizontalOptions = LayoutOptions.End,
            VerticalOptions = LayoutOptions.Center
        }
        .Binding(Label.TextProperty, nameof(Detail))
        .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor);
    }

    public class OptionSelectCell : OptionTextCell
    {
        public static readonly BindableProperty CommandProperty = BindableProperty.Create(nameof(Command), typeof(Command), typeof(OptionSelectCell));
        public static readonly BindableProperty CommandParameterProperty = BindableProperty.Create(nameof(CommandParameter), typeof(object), typeof(OptionSelectCell));

        public Command Command
        {
            get => (Command)GetValue(CommandProperty);
            set => SetValue(CommandProperty, value);
        }
        public object CommandParameter
        {
            get => GetValue(CommandParameterProperty);
            set => SetValue(CommandParameterProperty, value);
        }

        protected override View Content => new StackLayout
        {
            Orientation = StackOrientation.Horizontal,
            HorizontalOptions = LayoutOptions.End,
            Children =
            {
                new Label
                {
                    HorizontalOptions = LayoutOptions.End,
                    VerticalOptions = LayoutOptions.Center
                }
                .Binding(Label.TextProperty, nameof(Detail))
                .DynamicResource(Label.TextColorProperty, BaseTheme.SecondaryTextColor),

                new TintImage
                {
                    HeightRequest = 20,
                    VerticalOptions = LayoutOptions.Center,
                    Margin = new Thickness(6, 0),
                    Source = "right.png"
                }
            },
            GestureRecognizers =
            {
                new TapGestureRecognizer()
                    .Binding(TapGestureRecognizer.CommandProperty, nameof(Command))
                    .Binding(TapGestureRecognizer.CommandParameterProperty, nameof(CommandParameter))
            }
        };
    }

    public class OptionSwitchCell : OptionCell
    {
        public static readonly BindableProperty IsToggledProperty = BindableProperty.Create(nameof(IsToggled), typeof(bool), typeof(OptionSwitchCell));

        public bool IsToggled
        {
            get => (bool)GetValue(IsToggledProperty);
            set => SetValue(IsToggledProperty, value);
        }

        protected override View Content => new Switch
        {
            HorizontalOptions = LayoutOptions.End,
            VerticalOptions = LayoutOptions.Center
        }
        .Binding(Switch.IsToggledProperty, nameof(IsToggled), BindingMode.TwoWay);
    }

    public class OptionEntryCell : OptionCell
    {
        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEntryCell));
        public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEntryCell));
        public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEntryCell));

        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }
        public Keyboard Keyboard
        {
            get => (Keyboard)GetValue(KeyboardProperty);
            set => SetValue(KeyboardProperty, value);
        }
        public string Placeholder
        {
            get => (string)GetValue(PlaceholderProperty);
            set => SetValue(PlaceholderProperty, value);
        }

        protected override View Content => new OptionEntry
        {
            HorizontalOptions = LayoutOptions.Fill,
            HorizontalTextAlignment = TextAlignment.End,
            VerticalOptions = LayoutOptions.Center,
            ReturnType = ReturnType.Next
        }
        .Binding(Entry.TextProperty, nameof(Text), BindingMode.TwoWay)
        .Binding(InputView.KeyboardProperty, nameof(Keyboard))
        .Binding(Entry.PlaceholderProperty, nameof(Placeholder))
        .DynamicResource(Entry.TextColorProperty, BaseTheme.TextColor)
        .DynamicResource(Entry.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
        .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
    }

    public class OptionEditorCell : OptionVerticalCell
    {
        public static readonly BindableProperty TextProperty = BindableProperty.Create(nameof(Text), typeof(string), typeof(OptionEditorCell));
        public static readonly BindableProperty FontSizeProperty = BindableProperty.Create(nameof(FontSize), typeof(double), typeof(OptionEditorCell), defaultValue: Device.GetNamedSize(NamedSize.Default, typeof(Editor)));
        public static readonly BindableProperty KeyboardProperty = BindableProperty.Create(nameof(Keyboard), typeof(Keyboard), typeof(OptionEditorCell), defaultValue: Keyboard.Default);
        public static readonly BindableProperty PlaceholderProperty = BindableProperty.Create(nameof(Placeholder), typeof(string), typeof(OptionEditorCell));

        public string Text
        {
            get => (string)GetValue(TextProperty);
            set => SetValue(TextProperty, value);
        }
        [TypeConverter(typeof(FontSizeConverter))]
        public double FontSize
        {
            get => (double)GetValue(FontSizeProperty);
            set => SetValue(FontSizeProperty, value);
        }
        public Keyboard Keyboard
        {
            get => (Keyboard)GetValue(KeyboardProperty);
            set => SetValue(KeyboardProperty, value);
        }
        public string Placeholder
        {
            get => (string)GetValue(PlaceholderProperty);
            set => SetValue(PlaceholderProperty, value);
        }

        protected override View Content => new OptionEditor
        {
            HorizontalOptions = LayoutOptions.Fill,
            VerticalOptions = LayoutOptions.Fill
        }
        .Binding(Editor.TextProperty, nameof(Text), BindingMode.TwoWay)
        .Binding(Editor.FontSizeProperty, nameof(FontSize))
        .Binding(InputView.KeyboardProperty, nameof(Keyboard))
        .Binding(Editor.PlaceholderProperty, nameof(Placeholder))
        .DynamicResource(Editor.TextColorProperty, BaseTheme.TextColor)
        .DynamicResource(Editor.PlaceholderColorProperty, BaseTheme.SecondaryTextColor)
        .DynamicResource(VisualElement.BackgroundColorProperty, BaseTheme.OptionTintColor);
    }
}
