using System;
using System.Windows;

namespace HandyControl.Expression.Media
{
    internal class DrawingPropertyMetadata : FrameworkPropertyMetadata
    {
#pragma warning disable 414
        private DrawingPropertyMetadataOptions options;
#pragma warning restore 414

        private PropertyChangedCallback propertyChangedCallback;

        public static event EventHandler<DrawingPropertyChangedEventArgs> DrawingPropertyChanged;

        static DrawingPropertyMetadata()
        {
            DrawingPropertyChanged += delegate (object sender, DrawingPropertyChangedEventArgs args) {
                if ((sender is IShape shape) && args.Metadata.AffectsRender)
                {
                    InvalidateGeometryReasons reasons = InvalidateGeometryReasons.PropertyChanged;
                    if (args.IsAnimated)
                    {
                        reasons |= InvalidateGeometryReasons.IsAnimated;
                    }
                    shape.InvalidateGeometry(reasons);
                }
            };
        }

        public DrawingPropertyMetadata(object defaultValue) : this(defaultValue, DrawingPropertyMetadataOptions.None, null)
        {
        }

        public DrawingPropertyMetadata(PropertyChangedCallback propertyChangedCallback) : this(DependencyProperty.UnsetValue, DrawingPropertyMetadataOptions.None, propertyChangedCallback)
        {
        }

        private DrawingPropertyMetadata(DrawingPropertyMetadataOptions options, object defaultValue) : base(defaultValue, (FrameworkPropertyMetadataOptions)options)
        {
        }

        public DrawingPropertyMetadata(object defaultValue, DrawingPropertyMetadataOptions options) : this(defaultValue, options, null)
        {
        }

        public DrawingPropertyMetadata(object defaultValue, DrawingPropertyMetadataOptions options, PropertyChangedCallback propertyChangedCallback) : base(defaultValue, (FrameworkPropertyMetadataOptions)options, AttachCallback(defaultValue, options, propertyChangedCallback))
        {
        }

        private static PropertyChangedCallback AttachCallback(object defaultValue, DrawingPropertyMetadataOptions options, PropertyChangedCallback propertyChangedCallback)
        {
            DrawingPropertyMetadata metadata = new DrawingPropertyMetadata(options, defaultValue)
            {
                options = options,
                propertyChangedCallback = propertyChangedCallback
            };
            return metadata.InternalCallback;
        }

        private void InternalCallback(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            if (DrawingPropertyChanged != null)
            {
                DrawingPropertyChangedEventArgs args = new DrawingPropertyChangedEventArgs
                {
                    Metadata = this,
                    IsAnimated = DependencyPropertyHelper.GetValueSource(sender, e.Property).IsAnimated
                };
                DrawingPropertyChanged(sender, args);
            }

            propertyChangedCallback?.Invoke(sender, e);
        }
    }
}