using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;

namespace HandyControl.Controls;

public class FlipClock : Control
{
    private readonly DispatcherTimer _dispatcherTimer;

    private bool _isDisposed;

    public static readonly DependencyProperty NumberListProperty = DependencyProperty.Register(
        nameof(NumberList), typeof(List<int>), typeof(FlipClock), new PropertyMetadata(new List<int> { 0, 0, 0, 0, 0, 0 }));

    public List<int> NumberList
    {
        get => (List<int>) GetValue(NumberListProperty);
        set => SetValue(NumberListProperty, value);
    }

    public static readonly DependencyProperty DisplayTimeProperty = DependencyProperty.Register(
        nameof(DisplayTime), typeof(DateTime), typeof(FlipClock), new PropertyMetadata(default(DateTime), OnDisplayTimeChanged));

    private static void OnDisplayTimeChanged(DependencyObject s, DependencyPropertyChangedEventArgs e)
    {
        var ctl = (FlipClock) s;
        var v = (DateTime) e.NewValue;

        ctl.NumberList = new List<int>
        {
            v.Hour / 10,
            v.Hour % 10,
            v.Minute / 10,
            v.Minute % 10,
            v.Second / 10,
            v.Second % 10
        };
    }

    public DateTime DisplayTime
    {
        get => (DateTime) GetValue(DisplayTimeProperty);
        set => SetValue(DisplayTimeProperty, value);
    }

    public FlipClock()
    {
        _dispatcherTimer = new DispatcherTimer(DispatcherPriority.Render)
        {
            Interval = TimeSpan.FromMilliseconds(200)
        };

        IsVisibleChanged += FlipClock_IsVisibleChanged;
    }

    ~FlipClock() => Dispose();

    public void Dispose()
    {
        if (_isDisposed) return;

        IsVisibleChanged -= FlipClock_IsVisibleChanged;
        _dispatcherTimer.Stop();
        _isDisposed = true;

        GC.SuppressFinalize(this);
    }

    private void FlipClock_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        if (IsVisible)
        {
            _dispatcherTimer.Tick += DispatcherTimer_Tick;
            _dispatcherTimer.Start();
        }
        else
        {
            _dispatcherTimer.Stop();
            _dispatcherTimer.Tick -= DispatcherTimer_Tick;
        }
    }

    private void DispatcherTimer_Tick(object sender, EventArgs e) => DisplayTime = DateTime.Now;
}
