using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using System.Threading;
using System.Windows.Media.Imaging;
using Ion.Sdk.DemoApp.Framework;

namespace Ion.Sdk.DemoApp.Views.Controls
{
    /// <summary>
    /// ContentControl that shows last shown content appearance for a specific period of time.
    /// Burned content is shown only after Content has been reset to null value.
    /// </summary>
    [TemplatePart(Name = "PART_PaintedContent", Type = typeof(Shape))]
    [TemplatePart(Name = "PART_Content", Type = typeof(ContentPresenter))]
    public class BurnInContent : ContentControl {
        #region -=Instance members=-
        private Shape paintedContent;
        private ContentPresenter contentPresentor;
        private readonly Timer timer = null;
        #region -=Dependency properties=-
        public int BurnInTime {
            get { return (int)GetValue(BurnInTimeProperty); }
            set { SetValue(BurnInTimeProperty, value); }
        }
        #endregion
        public BurnInContent()
        {
            timer = new Timer(OnTimerElapsed);
        }

        public override void OnApplyTemplate() {
            paintedContent = Template.FindName("PART_PaintedContent", this) as Shape;
            contentPresentor = Template.FindName("PART_Content", this) as ContentPresenter;
            base.OnApplyTemplate();
        }

        protected override void OnContentChanged(object oldContent, object newContent) {
            if (this.BurnInTime > 0) {
                if (paintedContent != null && contentPresentor != null) {
                    if (newContent == null && oldContent is FrameworkElement element && ActualHeight > 0 && ActualWidth > 0) {
                        SetBurnIn();
                    } else
                        ClearBurnIn();
                    contentPresentor.Content = newContent;
                }
            }
            base.OnContentChanged(oldContent, newContent);
        }
        protected override void OnContentTemplateChanged(DataTemplate oldContentTemplate, DataTemplate newContentTemplate) {
            if (BurnInTime > 0) {
                if (paintedContent != null && contentPresentor != null) {
                    if (newContentTemplate == null && oldContentTemplate != null && ActualHeight > 0 && ActualWidth > 0)
                        SetBurnIn();
                    else
                        ClearBurnIn();
                    contentPresentor.ContentTemplate = newContentTemplate;
                }
            }
            base.OnContentTemplateChanged(oldContentTemplate, newContentTemplate);
        }

        private void OnTimerElapsed(object state) {
            Dispatcher.Invoke(() => {
                if (paintedContent != null) {
                    ClearBurnIn();
                }
            });
        }
        private void ClearBurnIn() {
            timer.Change(Timeout.Infinite, Timeout.Infinite);
            paintedContent.Fill = null;
            paintedContent.Visibility = Visibility.Collapsed;
        }
        private void SetBurnIn() {
            paintedContent.Fill = GetBrush();
            paintedContent.Visibility = Visibility.Visible;
            paintedContent.Height = ActualHeight;
            paintedContent.Width = ActualWidth;
            timer.Change(BurnInTime, Timeout.Infinite);
        }
        private ImageBrush GetBrush() {
            ImageBrush brush = contentPresentor.CreateBrush((int)ActualWidth, (int)ActualHeight);
            brush.Freeze();
            return brush;
        }

        #endregion
        #region -=Static members=-
        public static readonly DependencyProperty BurnInTimeProperty = DependencyProperty.Register("BurnInTime", typeof(int), typeof(BurnInContent), new UIPropertyMetadata(300));
        /// <summary>
        /// Auto-generated static constructor.
        /// </summary>
        static BurnInContent() {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(BurnInContent), new FrameworkPropertyMetadata(typeof(BurnInContent)));
        }
        #endregion
    }
}
