using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace ProximaAnalizer.Controls
{
    /// <summary>
    /// Interaction logic for AlarmPicker.xaml
    /// </summary>
    public partial class AlarmPicker : UserControl
    {
        public AlarmPicker()
        {
            InitializeComponent();
            this._keyboardHook = new();
            this._keyboardHook.SetHook();
            this._keyboardHook.SetOnKeyUpEvent(Win32_Keydown);
        }

        private KeyboardHook _keyboardHook;

        private void Win32_Keydown(Key key)
        {
            switch (key)
            {
                case Key.Enter:
                    if (this.SelectedPage > this.TotalPage || this.SelectedPage <= 0)
                        return;
                    this.Display = this.AlarmSource.Skip((int)(this.SelectedPage - 1) * (int)this.ItemsPerPage).Take((int)this.ItemsPerPage).ToDictionary();
                    break;
                case Key.Right:
                    this.Next_Click(this, default);
                    break;
                case Key.Left:
                    this.Prev_Click(this, default);
                    break;
                case Key.Home:
                    this.Home_Click(this, default);
                    break;
                case Key.End:
                    this.End_Click(this, default);
                    break;
                case Key.Escape:
                    this.IsPopOpen = false;
                    break;
                default:
                    break;
            }
        }

        public object SelectedAlarm
        {
            get { return (object)GetValue(SelectedAlarmProperty); }
            set { SetValue(SelectedAlarmProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedAlarm.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedAlarmProperty =
            DependencyProperty.Register("SelectedAlarm", typeof(object), typeof(AlarmPicker), new System.Windows.PropertyMetadata(default));

        private IDictionary<DateTime, StringBuilder> Display
        {
            get { return (IDictionary<DateTime, StringBuilder>)GetValue(DisplayProperty); }
            set { SetValue(DisplayProperty, value); }
        }

        public static readonly DependencyProperty DisplayProperty =
            DependencyProperty.Register("Display", typeof(IDictionary<DateTime, StringBuilder>), typeof(AlarmPicker), new System.Windows.PropertyMetadata(default));


        public IDictionary<DateTime, StringBuilder> AlarmSource
        {
            get { return (IDictionary<DateTime, StringBuilder>)GetValue(AlarmSourceProperty); }
            set { SetValue(AlarmSourceProperty, value); }
        }

        public static readonly DependencyProperty AlarmSourceProperty =
            DependencyProperty.Register("AlarmSource", typeof(IDictionary<DateTime, StringBuilder>), typeof(AlarmPicker), new System.Windows.PropertyMetadata(default, AlarmChangedCallback));

        private static void AlarmChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not AlarmPicker alarmPicker)
                return;

            if (e.NewValue is not IDictionary<DateTime, StringBuilder> alarms)
                return;

            if (alarmPicker.ItemsPerPage == 0)
                alarmPicker.ItemsPerPage = 10;

            alarmPicker.Display = alarms.Take(10).ToDictionary();
            alarmPicker.SelectedPage = 1;
            alarmPicker.TotalPage = (uint)(alarms.Count / alarmPicker.ItemsPerPage);
            if ((alarms.Count % alarmPicker.ItemsPerPage) != 0)
                alarmPicker.TotalPage += 1;
        }



        public uint ItemsPerPage
        {
            get { return (uint)GetValue(ItemsPerPageProperty); }
            set { SetValue(ItemsPerPageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for ItemsPerPage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty ItemsPerPageProperty =
            DependencyProperty.Register("ItemsPerPage", typeof(uint), typeof(AlarmPicker), new System.Windows.PropertyMetadata((uint)10));

        public uint SelectedPage
        {
            get { return (uint)GetValue(SelectedPageProperty); }
            set { SetValue(SelectedPageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for SelectedPage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty SelectedPageProperty =
            DependencyProperty.Register("SelectedPage", typeof(uint), typeof(AlarmPicker), new System.Windows.PropertyMetadata(default));


        public uint TotalPage
        {
            get { return (uint)GetValue(TotalPageProperty); }
            set { SetValue(TotalPageProperty, value); }
        }

        // Using a DependencyProperty as the backing store for TotalPage.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty TotalPageProperty =
            DependencyProperty.Register("TotalPage", typeof(uint), typeof(AlarmPicker), new System.Windows.PropertyMetadata(default));



        public bool IsPopOpen
        {
            get { return (bool)GetValue(IsPopOpenProperty); }
            set { SetValue(IsPopOpenProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsPopOpen.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsPopOpenProperty =
            DependencyProperty.Register("IsPopOpen", typeof(bool), typeof(AlarmPicker), new System.Windows.PropertyMetadata(false, PopChangedCallback));
        private static void PopChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is not AlarmPicker alarmPicker)
                return;

            if (e.NewValue is not bool isPop)
                return;

            switch (isPop)
            {
                case true:
                    alarmPicker._keyboardHook?.UnHook();
                    alarmPicker._keyboardHook = new();
                    alarmPicker._keyboardHook.SetHook();
                    alarmPicker._keyboardHook.SetOnKeyUpEvent(alarmPicker.Win32_Keydown);
                    break;
                case false:
                    alarmPicker._keyboardHook.UnHook();
                    break;
            }
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            if (sender is not Button button)
                return;

            this.SelectedAlarm = button.CommandParameter;
            this.IsPopOpen = false;
        }

        private void Next_Click(object sender, RoutedEventArgs? e)
        {
            if (this.SelectedPage == this.TotalPage)
                return;
            this.SelectedPage++;
            this.Display = this.AlarmSource.Skip((int)(this.SelectedPage - 1) * (int)this.ItemsPerPage).Take((int)this.ItemsPerPage).ToDictionary();
        }

        private void Prev_Click(object sender, RoutedEventArgs? e)
        {
            if (this.SelectedPage == 1)
                return;
            this.SelectedPage--;
            this.Display = this.AlarmSource.Skip((int)(this.SelectedPage - 1) * (int)this.ItemsPerPage).Take((int)this.ItemsPerPage).ToDictionary();
        }

        private void Home_Click(object sender, RoutedEventArgs? e)
        {
            this.SelectedPage = 1;
            this.Display = this.AlarmSource.Take((int)this.ItemsPerPage).ToDictionary();
        }

        private void End_Click(object sender, RoutedEventArgs? e)
        {
            this.SelectedPage = this.TotalPage;
            this.Display = this.AlarmSource.TakeLast((int)this.ItemsPerPage).ToDictionary();
        }

        private void Pop_Click(object sender, RoutedEventArgs? e)
        {
            this.IsPopOpen = true;


        }
    }
}
