using System;
using System.Collections.Generic;
using System.Reflection;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Linq;
using System.Threading.Tasks;

using F4SD_AdaptableIcon.Enums;

using FasdDesktopUi.Basics.Models;
using FasdDesktopUi.Basics.UiActions;
using FasdDesktopUi.Pages;
using FasdDesktopUi.Pages.SearchPage;

using C4IT.FASD.Base;
using static C4IT.Logging.cLogManager;
using F4SD_AdaptableIcon;

namespace FasdDesktopUi.Basics.UserControls
{
    public partial class MenuBar : UserControl
    {
        #region Properties

        #region PopUpIsVisible

        internal static readonly DependencyPropertyKey PopUpIsVisibleKey = DependencyProperty.RegisterReadOnly("PopUpIsVisible", typeof(bool), typeof(MenuBar), new PropertyMetadata(false));

        public static readonly DependencyProperty PopUpIsVisibleProperty = PopUpIsVisibleKey.DependencyProperty;

        public bool PopUpIsVisible => (bool)GetValue(PopUpIsVisibleProperty);

        #endregion

        #region SearchBarIsVisible

        private static void SearchBarIsVisibleChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is MenuBar _me && e.NewValue is bool searchBarIsVisible)
                _me.SetValue(PopUpIsVisibleKey, searchBarIsVisible);
        }

        public static readonly DependencyProperty SearchBarIsVisibleProperty =
            DependencyProperty.Register("SearchBarIsVisible", typeof(bool), typeof(MenuBar), new PropertyMetadata(false, new PropertyChangedCallback(SearchBarIsVisibleChangedCallback)));

        public bool SearchBarIsVisible
        {
            get { return (bool)GetValue(SearchBarIsVisibleProperty); }
            set { SetValue(SearchBarIsVisibleProperty, value); }
        }

        #endregion

        #region MenubarItemData DependencyProperty

        public static readonly DependencyProperty MenuBarItemDataProperty =
            DependencyProperty.Register("MenuBarItemData", typeof(List<cMenuDataBase>), typeof(MenuBar), new PropertyMetadata(new List<cMenuDataBase>(), new PropertyChangedCallback(MenuBarChangedCallBack)));

        private static void MenuBarChangedCallBack(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            if (d is MenuBar _me)
            {
                _me.MenuBarStackPanel.Children.RemoveRange(2, _me.MenuBarStackPanel.Children.Count - 3);
                _me.SetUpMenuBar();
            }
        }

        public List<cMenuDataBase> MenuBarItemData
        {
            get { return (List<cMenuDataBase>)GetValue(MenuBarItemDataProperty); }
            set { SetValue(MenuBarItemDataProperty, value); }
        }

        #endregion

        public void SetSlimPage()
        {
            Dispatcher.Invoke(new Action(() =>
            {
                NotepadButton.Visibility = Visibility.Collapsed;
            }));
        }

        public Action SearchButtonClickedAction { get; set; }

        public Action MoreButtonClickedAction { get; set; }

        #endregion

        public MenuBar()
        {
            InitializeComponent();
        }

        private void SetUpMenuBar()
        {
            var CM = MethodBase.GetCurrentMethod();
            LogMethodBegin(CM);
            try
            {
                if (MenuBarItemData == null)
                    return;

                var sortedMenuData = MenuBarItemData.OrderBy(x => x.IconPositionIndex).ToList();

                for (int i = 0; i < sortedMenuData.Count; i++)
                {
                    AdaptableIcon.AdaptableIcon menuIcon = new AdaptableIcon.AdaptableIcon() { Style = menuPinnedIconStyle };

                    IconData icon = sortedMenuData[i].MenuIcon;
                    if (icon.Intern != null)
                        menuIcon.SelectedInternIcon = icon.Intern;
                    else if(icon.Material != null)
                        menuIcon.SelectedMaterialIcon = icon.Material;

                    menuIcon.Tag = sortedMenuData[i];

                    string toolTipText = sortedMenuData[i].MenuText;

                    if (sortedMenuData[i].UiAction?.DisplayType != Enums.enumActionDisplayType.enabled)
                    {
                        menuIcon.Opacity = 0.5;

                        if (string.IsNullOrEmpty(sortedMenuData[i].UiAction?.AlternativeDescription) == false)
                            toolTipText += "\n" + sortedMenuData[i].UiAction?.AlternativeDescription;

                        menuIcon.Style = menuPinnedIconNoHoverStyle;
                    }
                    else
                    {
                        if (string.IsNullOrEmpty(sortedMenuData[i].UiAction?.Description) == false)
                            toolTipText += "\n" + sortedMenuData[i].UiAction?.Description;

                        menuIcon.MouseLeftButtonUp += MenuItem_MouseUp;
                        menuIcon.TouchDown += MenuItem_TouchDown;
                    }

                    menuIcon.ToolTip = toolTipText;

                    if (sortedMenuData[i].IconPositionIndex >= 0)
                        MenuBarStackPanel.Children.Insert(MenuBarStackPanel.Children.Count - 1, menuIcon);
                }

                if (cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate != null)
                {
                    var copyIcon = new AdaptableIcon.AdaptableIcon()
                    {
                        Style = menuPinnedIconStyle,
                        SelectedInternIcon = enumInternIcons.menuBar_copy,
                        ToolTip = cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate.Descriptions.GetValue(Default: null),
                    };

                    copyIcon.Tag = new cMenuDataBase() { IconPositionIndex = 2, MenuIcon = new F4SD_AdaptableIcon.IconData(enumInternIcons.menuBar_copy), UiAction = new cUiCopyAction(cF4SDCockpitXmlConfig.Instance?.CopyTemplateConfig?.CopyTemplates.DefaultTemplate) };

                    copyIcon.MouseLeftButtonUp += MenuItem_MouseUp;
                    copyIcon.TouchDown += MenuItem_TouchDown;

                    MenuBarStackPanel.Children.Insert(2, copyIcon);
                }
            }
            catch (Exception E)
            {
                LogException(E);
            }
            finally
            {
                LogMethodEnd(CM);
            }
        }

        #region Styles

        private Style menuPinnedIconStyle;
        private Style menuPinnedIconNoHoverStyle;

        private void SetStyles()
        {
            menuPinnedIconStyle = (Style)FindResource("Menu.MenuBar.PinnedIcon");
            menuPinnedIconNoHoverStyle = (Style)FindResource("Menu.MenuBar.PinnedIcon.Base");
        }

        #endregion

        #region Events

        #region UserControl

        private void UserControl_Initialized(object sender, EventArgs e)
        {
            SetStyles();
            SearchBarIsVisible = false;
        }

        #endregion

        #region MenuItem Click

        private async Task MenuItem_ClickAsync(object sender)
        {
            if (!(sender is FrameworkElement FE))
                return;

            if (!(FE.Tag is cMenuDataBase MenuData))
                return;

            if (MenuData.UiAction == null)
                return;

            cUiActionBase.RaiseEvent(MenuData.UiAction, this, this);

            if (MenuData.UiAction is cUiCopyAction && FE is AdaptableIcon.AdaptableIcon adaptableIcon)
                await cUtility.ChangeIconToCheckAsync(adaptableIcon);
        }

        private async void MenuItem_TouchDown(object sender, TouchEventArgs e) => await MenuItem_ClickAsync(sender);

        private async void MenuItem_MouseUp(object sender, MouseButtonEventArgs e) => await MenuItem_ClickAsync(sender);

        #endregion

        #region MoreButton Click

        private void MoreButton_Click()
        {
            SearchBarIsVisible = false;
            RaiseMoreQuickActionsButtonWasClickedEvent();
            MoreButtonClickedAction?.Invoke();
        }

        private void MoreButton_MouseUp(object sender, MouseButtonEventArgs e)
        {
            MoreButton_Click();
        }

        private void MoreButton_TouchDown(object sender, TouchEventArgs e)
        {
            MoreButton_Click();
        }

        #endregion

        #region SearchButton Click

        private void SearchButton_Click()
        {
            try
            {
                if (SearchPageView.Instance.IsVisible)
                    SearchPageView.Instance.Hide();
                else
                    SearchPageView.Instance.ActivateSearchView();
            }
            catch (Exception E)
            {
                LogException(E);
            }
        }

        private void SearchButton_MouseUp(object sender, MouseButtonEventArgs e) => SearchButton_Click();

        private void SearchButton_TouchDown(object sender, TouchEventArgs e) => SearchButton_Click();

        #endregion

        #region ChangedMenuPopUpStatus

        public static readonly RoutedEvent MoreQuickActionsButtonWasClicked = EventManager.RegisterRoutedEvent("MoreQuickActionsButtonWasClickedEventHandler", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(MenuBar));

        public event RoutedEventHandler MoreQuickActionsButtonWasClickedEventHandler
        {
            add { AddHandler(MoreQuickActionsButtonWasClicked, value); }
            remove { RemoveHandler(MoreQuickActionsButtonWasClicked, value); }
        }

        private void RaiseMoreQuickActionsButtonWasClickedEvent()
        {
            RoutedEventArgs newEventArgs = new RoutedEventArgs(MoreQuickActionsButtonWasClicked);
            RaiseEvent(newEventArgs);
        }

        #endregion

        #endregion

        #region NotepadButton Click

        private void NotepadButton_Click()
        {

            try
            {

                if (cFasdCockpitConfig.Instance.IsNotepadVisibleDocked == true)
                {
                    return;
                }

                cUiActionBase.RaiseEvent(new cUiShowNotepadQuickAction(), this, this);
            }
            catch (Exception E)
            {
                LogException(E);
            }

        }

        private void NotepadButton_TouchDown(object sender, TouchEventArgs e)
        {
            NotepadButton_Click();
        }

        private void NotepadButton_MouseUp(object sender, MouseButtonEventArgs e)
        {
            NotepadButton_Click();
        }

        #endregion

        public void ChangeNotepadNotificationVisibility(bool visible)
        {
            if (visible)
                NotepadNotificationBorder.Visibility = Visibility.Visible;
            else
                NotepadNotificationBorder.Visibility = Visibility.Collapsed;
        }
    }
}
