using System;
using System.ComponentModel;
using System.Globalization;
using InABox.Core;
using Syncfusion.XForms.PopupLayout;

using Xamarin.Forms;
using Xamarin.Forms.Xaml;
using XF.Material.Forms.Resources.Typography;
using CancelEventArgs = Syncfusion.XForms.Core.CancelEventArgs;

namespace InABox.Mobile
{
    
    public class DateButtonChangedArgs : EventArgs
    {
        public DateTime Date { get; private set; }

        public DateButtonChangedArgs(DateTime date)
        {
            Date = date;
        }
    }
    
    public delegate void DateButtonChanged(object sender, DateButtonChangedArgs args);

    public class DateTimeFormatter : AbstractConverter<DateTime,String>
    {
        public String Prefix { get; set; }
        public String Format { get; set; }
        public String Prompt { get; set; }

        private DateTime _value;
        protected override string Convert(DateTime value, object? parameter = null)
        {
            _value = value;
            if (!value.IsEmpty())
            {
                var sFormat = String.IsNullOrWhiteSpace(Format)
                    ? "dd MMMM yy"
                    : Format;
                String fmt = "{0} {1:" + sFormat + "}";
                return String.Format(fmt,Prefix,value).Trim();
            }
            return String.IsNullOrWhiteSpace(Prompt)
                ? "Select Date"
                : Prompt;
        }

        protected override DateTime Deconvert(string value, object? parameter = null)
        {
            return _value;
        }
    }
    
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class MobileDateButton
    {
        public event DateButtonChanged Changed;
        
        public static readonly BindableProperty PromptProperty = BindableProperty.Create(
            nameof(Prompt), 
            typeof(string), 
            typeof(MobileDateButton)
        );
        
        public String Prompt
        {
            get => (string)GetValue(PromptProperty);
            set
            {
                _datetimeformatter.Prompt = value;
                SetValue(PromptProperty, value);
            }
        }
        
        public static readonly BindableProperty PrefixProperty = BindableProperty.Create(
            nameof(Prefix), 
            typeof(string), 
            typeof(MobileDateButton)
        );
        
        public String Prefix
        {
            get => (string)GetValue(PrefixProperty);
            set
            {
                _datetimeformatter.Prefix = value;
                SetValue(PrefixProperty, value);
            }
        }
        
        public static readonly BindableProperty FormatProperty = BindableProperty.Create(
            nameof(Format), 
            typeof(string), 
            typeof(MobileDateButton)
        );
        
        public String Format
        {
            get => (string)GetValue(FormatProperty);
            set
            {
                _datetimeformatter.Format = value;
                SetValue(FormatProperty, value);
            }
        }

        public static readonly BindableProperty DateProperty = BindableProperty.Create(
            nameof(Date), 
            typeof(DateTime), 
            typeof(MobileDateButton)
        );

        public DateTime Date
        {
            get => (DateTime)GetValue(DateProperty);
            set => SetValue(DateProperty,value);
        }

        private static readonly BindableProperty TextColorProperty = BindableProperty.Create(
            nameof(TextColor),
            typeof(Color),
            typeof(MobileDateButton),
            XF.Material.Forms.Material.Color.OnSecondary);

        public Color TextColor
        {
            get => (Color)GetValue(TextColorProperty);
            set => SetValue(TextColorProperty, value);
        }

        private static readonly BindableProperty TypeScaleProperty = BindableProperty.Create(
            nameof(TypeScale), 
            typeof(MaterialTypeScale), 
            typeof(MobileDateButton), 
            MaterialTypeScale.Button);
        
        public MaterialTypeScale TypeScale
        {
            get => (MaterialTypeScale)GetValue(TypeScaleProperty);
            set => SetValue(TypeScaleProperty, value);
        }

        private static readonly BindableProperty ButtonColorProperty = BindableProperty.Create(
            nameof(ButtonColor),
            typeof(Color),
            typeof(MobileDateButton),
            XF.Material.Forms.Material.Color.Secondary);

        public Color ButtonColor
        {
            get => (Color)GetValue(ButtonColorProperty);
            set => SetValue(ButtonColorProperty, value);
        }

        private static readonly BindableProperty BorderColorProperty = BindableProperty.Create(
            nameof(BorderColor),
            typeof(Color),
            typeof(MobileDateButton),
            XF.Material.Forms.Material.Color.SecondaryVariant);

        public Color BorderColor
        {
            get => (Color)GetValue(BorderColorProperty);
            set => SetValue(BorderColorProperty, value);
        }
        
        public MobileDateButton()
        {
            InitializeComponent();
        }

        private void _frame_OnClicked(object sender, EventArgs e)
        {
            MobileDateSelector popupContent = new MobileDateSelector();
            popupContent.Date = Date;
            popupContent.Changed += (o, args) =>
            {
                Date = args.Date;
                DoChanged();
                PopupManager.DismissPopup();
            };
            popupContent.Cancelled += (o, args) =>
            {
                PopupManager.DismissPopup();
            };
            popupContent.HorizontalOptions = LayoutOptions.Fill;
            popupContent.VerticalOptions = LayoutOptions.Fill;
            
            PopupManager.ShowPopup(
                this, 
                () => popupContent, 
                new PopupManagerConfiguration()
                {
                    Modal = true,
                    RequestedHeight = 500,
                    RequestedWidth = 350
                }
            );   
        }

        protected virtual void DoChanged()
        {
            Changed?.Invoke(this,new DateButtonChangedArgs(Date));
        }


        private void DateTimeFormatter_OnPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            OnPropertyChanged(nameof(Date));
        }
    }
}