using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Text;
using System.Windows.Input;
using System.Windows;

namespace HandyControl.Interactivity
{
    public class ExCommandParameter
    {
        /// <summary>

        /// 事件触发源

        /// </summary>
        [AllowNull]
        public DependencyObject Sender { get; set; }

        /// <summary>

        /// 事件参数

        /// </summary>
        [AllowNull]
        public EventArgs EventArgs { get; set; }

        /// <summary>

        /// 额外参数

        /// </summary>
        [AllowNull]
        public object Parameter { get; set; }
        [AllowNull]
        public object CommandName { get; set; }

    }
    public class ExInvokeCommandAction : TriggerAction<DependencyObject>
    {


       /* public bool IsEnabled
        {
            get { return (bool)GetValue(IsEnabledProperty); }
            set { SetValue(IsEnabledProperty, value); }
        }

        // Using a DependencyProperty as the backing store for IsEnabled.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty IsEnabledProperty =
            DependencyProperty.Register("IsEnabled", typeof(bool), typeof(ExInvokeCommandAction), new PropertyMetadata(true));
       */


        public static readonly DependencyProperty CommandNameProperty = DependencyProperty.Register("CommandName", typeof(object), typeof(ExInvokeCommandAction), null);

        public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(ExInvokeCommandAction), null);

        public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExInvokeCommandAction), null);

        /// <summary>

        /// 获得或设置此操作应调用的命令的名称。

        /// </summary>

        /// <value>此操作应调用的命令的名称。</value>

        /// <remarks>如果设置了此属性和 Command 属性，则此属性将被后者所取代。</remarks>

        public object CommandName
        {

            get
            {

                base.ReadPreamble();

                return GetValue(CommandNameProperty);

            }

            set
            {

                if (this.CommandName != value)
                {

                    base.WritePreamble();

                    SetValue(CommandNameProperty, value);

                    base.WritePostscript();

                }

            }

        }

        /// <summary>

        /// 获取或设置此操作应调用的命令。这是依赖属性。

        /// </summary>

        /// <value>要执行的命令。</value>

        /// <remarks>如果设置了此属性和 CommandName 属性，则此属性将优先于后者。</remarks>

        public ICommand Command
        {

            get
            {

                return (ICommand)GetValue(CommandProperty);

            }

            set
            {

                SetValue(CommandProperty, value);

            }

        }

        /// <summary>

        /// 获得或设置命令参数。这是依赖属性。

        /// </summary>

        /// <value>命令参数。</value>

        /// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>

        public object CommandParameter
        {

            get
            {

                return GetValue(CommandParameterProperty);

            }

            set
            {

                SetValue(CommandParameterProperty, value);

            }

        }

        /// <summary>

        /// 调用操作。

        /// </summary>

        /// <param name="parameter">操作的参数。如果操作不需要参数，则可以将参数设置为空引用。</param>

        protected override void Invoke(object parameter)
        {

            if (base.AssociatedObject != null)
            {

                ICommand? command = this.ResolveCommand();
                if (command == null) return;


                /*

				 * ★★★★★★★★★★★★★★★★★★★★★★★★

				 * 注意这里添加了事件触发源和事件参数

				 * ★★★★★★★★★★★★★★★★★★★★★★★★

				 */

                ExCommandParameter exParameter = new ExCommandParameter
                {

                    Sender = base.AssociatedObject,

                    Parameter = GetValue(CommandParameterProperty),

                    EventArgs = parameter as EventArgs,

                    CommandName = GetValue(CommandNameProperty)

                };



                if (command != null && command.CanExecute(exParameter))
                {

                    /*

					 * ★★★★★★★★★★★★★★★★★★★★★★★★

					 * 注意将扩展的参数传递到Execute方法中

					 * ★★★★★★★★★★★★★★★★★★★★★★★★

					 */

                    command.Execute(exParameter);

                }

            }

        }

        private ICommand? ResolveCommand()
        {

            ICommand? result = null;

            if (this.Command != null)
            {

                result = this.Command;

            }
            else
            {

                if (base.AssociatedObject != null)
                {

                    Type type = base.AssociatedObject.GetType();

                    PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);

                    PropertyInfo[] array = properties;

                    for (int i = 0; i < array.Length; i++)
                    {

                        PropertyInfo propertyInfo = array[i];

                        if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName?.ToString(), StringComparison.Ordinal))
                        {

                            result = (ICommand?)propertyInfo.GetValue(base.AssociatedObject, null);

                        }

                    }

                }

            }

            return result;

        }



    }
}
