using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Input;
using System.Windows.Media;

namespace MainShell.Common
{
    public static class FocusedEditorCommitHelper
    {
        public static void CommitFocusedEditorChanges()
        {
            var focusedElement = Keyboard.FocusedElement as DependencyObject;
            if (focusedElement == null)
                return;

            CommitBinding(focusedElement);

            var dataGrid = FindAncestor<DataGrid>(focusedElement);
            if (dataGrid != null)
            {
                dataGrid.CommitEdit(DataGridEditingUnit.Cell, true);
                dataGrid.CommitEdit(DataGridEditingUnit.Row, true);
            }
        }

        private static void CommitBinding(DependencyObject dependencyObject)
        {
            if (dependencyObject is TextBox textBox)
            {
                textBox.GetBindingExpression(TextBox.TextProperty)?.UpdateSource();
                return;
            }

            if (dependencyObject is ComboBox comboBox)
            {
                comboBox.GetBindingExpression(Selector.SelectedItemProperty)?.UpdateSource();
                comboBox.GetBindingExpression(ComboBox.TextProperty)?.UpdateSource();
                return;
            }

            if (dependencyObject is ToggleButton toggleButton)
            {
                toggleButton.GetBindingExpression(ToggleButton.IsCheckedProperty)?.UpdateSource();
            }
        }

        private static T FindAncestor<T>(DependencyObject dependencyObject) where T : DependencyObject
        {
            var current = dependencyObject;
            while (current != null)
            {
                if (current is T target)
                    return target;

                current = GetParent(current);
            }

            return null;
        }

        private static DependencyObject GetParent(DependencyObject dependencyObject)
        {
            if (dependencyObject is FrameworkElement frameworkElement)
            {
                return frameworkElement.Parent ?? VisualTreeHelper.GetParent(frameworkElement);
            }

            if (dependencyObject is FrameworkContentElement frameworkContentElement)
            {
                return frameworkContentElement.Parent;
            }

            return null;
        }
    }
}
