using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
using log4net;

namespace VIZ.Framework.Core
{
    /// <summary>
    /// WPF辅助类
    /// </summary>
    public static class WPFHelper
    {
        /// <summary>
        /// 日志
        /// </summary>
        private static ILog log = LogManager.GetLogger(typeof(WPFHelper));

        /// <summary>
        /// 当前是否处于设计模式
        /// </summary>
        /// <param name="control">控件</param>
        /// <returns>是否处于设计模式</returns>
        public static bool IsInDesignMode(DependencyObject control)
        {
            return System.ComponentModel.DesignerProperties.GetIsInDesignMode(control);
        }

        /// <summary>
        /// 绑定视图模型
        /// </summary>
        /// <param name="view">视图</param>
        /// <param name="vm">视图模型</param>
        public static void BindingViewModel(FrameworkElement view, ViewModelBase vm)
        {
            vm.SetView(view);
            view.DataContext = vm;
        }

        #region VisualTreeHelper -- 视觉树帮助

        /// <summary>
        /// 查找父级控件
        /// </summary>
        /// <typeparam name="T">要查找的父级控件类型</typeparam>
        /// <param name="element">查找的开始控件</param>
        /// <returns>查找结果</returns>
        public static T FindParent<T>(FrameworkElement element) where T : class
        {
            for (FrameworkElement e = element.TemplatedParent as FrameworkElement; e != null; e = e.TemplatedParent as FrameworkElement)
            {
                T local = e as T;
                if (local != null)
                    return local;
            }
            return default(T);
        }

        /// <summary>
        /// 查找父级控件
        /// </summary>
        /// <param name="type">父元素类型</param>
        /// <param name="element">查找的开始控件</param>
        /// <returns>查找结果</returns>
        public static object FindParent(FrameworkElement element, Type type)
        {
            for (FrameworkElement e = element.TemplatedParent as FrameworkElement; e != null; e = e.TemplatedParent as FrameworkElement)
            {
                if (e.GetType().Equals(type))
                    return e;
            }
            return null;
        }

        /// <summary>
        /// 使用可视化树查找父级控件
        /// </summary>
        /// <typeparam name="T">要查找的控件类型</typeparam>
        /// <param name="element">查找的开始控件</param>
        /// <returns>查找结果</returns>
        public static T GetAncestorByType<T>(DependencyObject element) where T : class
        {
            if (element == null)
                return default(T);

            if (element is T)
                return element as T;

            return GetAncestorByType<T>(System.Windows.Media.VisualTreeHelper.GetParent(element));
        }

        /// <summary>
        /// 使用可视化树查找父级控件
        /// </summary>
        /// <param name="type">父元素类型</param>
        /// <param name="element">查找的开始控件</param>
        /// <returns>查找结果</returns>
        public static object GetAncestorByType(DependencyObject element, Type type)
        {
            if (element == null)
                return null;

            if (element.GetType().Equals(type))
                return element;

            return GetAncestorByType(System.Windows.Media.VisualTreeHelper.GetParent(element), type);
        }

        #endregion

        #region UIThread -- UI线程

        /// <summary>
        /// 开始安全的UI同步更新
        /// </summary>
        /// <param name="action">行为</param>
        /// <param name="dispatcherPriority">优先级</param>
        public static void Invoke(Action action, DispatcherPriority dispatcherPriority = DispatcherPriority.Render)
        {
            Application.Current?.Dispatcher?.Invoke(new EventHandler<EventArgs>((o, e) =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }), dispatcherPriority, null, null);
        }

        /// <summary>
        /// 开始安全的UI同步更新
        /// </summary>
        /// <param name="action">行为</param>
        /// <param name="dispatcherPriority">优先级</param>
        public static void BeginInvoke(Action action, DispatcherPriority dispatcherPriority = DispatcherPriority.Render)
        {
            Application.Current?.Dispatcher?.BeginInvoke(new EventHandler<EventArgs>((o, e) =>
            {
                try
                {
                    action();
                }
                catch (Exception ex)
                {
                    log.Error(ex);
                }
            }), dispatcherPriority, null, null);
        }

        #endregion
    }
}
