using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace FasdDesktopUi.Basics.UserControls
{
    public partial class Badge : UserControl
    {
        private readonly Storyboard _sparkleStoryboard;
        private const double SparkleBaseScale = 0.6;

        public string Text
        {
            get { return (string)GetValue(TextProperty); }
            set { SetValue(TextProperty, value); }
        }

        public static readonly DependencyProperty TextProperty =
            DependencyProperty.Register(nameof(Text), typeof(string), typeof(Badge), new PropertyMetadata("Beta"));

        public bool IsSparkleEnabled
        {
            get { return (bool)GetValue(IsSparkleEnabledProperty); }
            set { SetValue(IsSparkleEnabledProperty, value); }
        }

        public static readonly DependencyProperty IsSparkleEnabledProperty =
            DependencyProperty.Register(nameof(IsSparkleEnabled), typeof(bool), typeof(Badge), new PropertyMetadata(false, OnIsSparkleEnabledChanged));


        public Badge()
        {
            InitializeComponent();
            _sparkleStoryboard = CreateSparkleStoryboard();
            UpdateSparkleState();
        }

        private static void OnIsSparkleEnabledChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var control = d as Badge;
            control?.UpdateSparkleState();
        }

        private void BadgeControl_Loaded(object sender, RoutedEventArgs e)
        {
            UpdateSparkleState();
        }

        private void BadgeControl_Unloaded(object sender, RoutedEventArgs e)
        {
            StopSparkles();
        }

        private void UpdateSparkleState()
        {
            if (SparkleCanvas == null || _sparkleStoryboard == null)
            {
                return;
            }

            if (IsSparkleEnabled)
            {
                SparkleCanvas.Visibility = Visibility.Visible;
                _sparkleStoryboard.Begin(this, true);
                return;
            }

            SparkleCanvas.Visibility = Visibility.Collapsed;
            StopSparkles();
        }

        private void StopSparkles()
        {
            _sparkleStoryboard?.Stop(this);

            if (SparkleTopRight != null)
            {
                SparkleTopRight.Opacity = 0;
                if (SparkleTopRight.RenderTransform is ScaleTransform topTransform)
                {
                    topTransform.ScaleX = SparkleBaseScale;
                    topTransform.ScaleY = SparkleBaseScale;
                }
            }

            if (SparkleBottomLeft != null)
            {
                SparkleBottomLeft.Opacity = 0;
                if (SparkleBottomLeft.RenderTransform is ScaleTransform bottomTransform)
                {
                    bottomTransform.ScaleX = SparkleBaseScale;
                    bottomTransform.ScaleY = SparkleBaseScale;
                }
            }
        }

        private Storyboard CreateSparkleStoryboard()
        {
            var storyboard = new Storyboard
            {
                RepeatBehavior = RepeatBehavior.Forever
            };

            AddKeyFrames(storyboard, SparkleTopRight, "Opacity",
                (0.00, 0.0), (0.18, 1.0), (0.42, 0.0), (2.20, 0.0));
            AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)",
                (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale));
            AddKeyFrames(storyboard, SparkleTopRight, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)",
                (0.00, SparkleBaseScale), (0.22, 1.15), (0.42, SparkleBaseScale), (2.20, SparkleBaseScale));

            AddKeyFrames(storyboard, SparkleBottomLeft, "Opacity",
                (0.00, 0.0), (1.00, 0.0), (1.18, 1.0), (1.42, 0.0), (2.20, 0.0));
            AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleX)",
                (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale));
            AddKeyFrames(storyboard, SparkleBottomLeft, "(UIElement.RenderTransform).(ScaleTransform.ScaleY)",
                (0.00, SparkleBaseScale), (1.00, SparkleBaseScale), (1.22, 1.15), (1.42, SparkleBaseScale), (2.20, SparkleBaseScale));

            return storyboard;
        }

        private static void AddKeyFrames(Storyboard storyboard, DependencyObject target, string targetProperty, params (double TimeSeconds, double Value)[] frames)
        {
            var animation = new DoubleAnimationUsingKeyFrames();

            foreach (var frame in frames)
            {
                animation.KeyFrames.Add(new LinearDoubleKeyFrame(frame.Value, KeyTime.FromTimeSpan(TimeSpan.FromSeconds(frame.TimeSeconds))));
            }

            Storyboard.SetTarget(animation, target);
            Storyboard.SetTargetProperty(animation, new PropertyPath(targetProperty));
            storyboard.Children.Add(animation);
        }
    }
}
