using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Layout;
using Avalonia.Markup.Xaml;
using Avalonia.Media;
using Avalonia.Metadata;
using System;
namespace InABox.Avalonia.Components;
/// 
/// Presents a control within a panel in which to zoom in and out and pan. The  must be a ,
/// and its  and  must be set.
/// 
[TemplatePart("PART_ZoomContent", typeof(ContentControl))]
[TemplatePart("PART_ZoomCanvas", typeof(Canvas))]
[TemplatePart("PART_ZoomContentBorder", typeof(Border))]
public partial class ZoomPanel : TemplatedControl
{
    public static readonly StyledProperty ContentProperty =
        AvaloniaProperty.Register(nameof(Content));
    [Content]
    public Layoutable? Content
    {
        get => GetValue(ContentProperty);
        set => SetValue(ContentProperty, value);
    }
    private double ContentWidth => Content?.Width ?? 1;
    private double ContentHeight => Content?.Height ?? 1;
    private Canvas OuterCanvas = null!;
    private ContentControl ZoomContent = null!;
    private Border ZoomContentBorder = null!;
    private double ScaleFactor = 1.0;
    private double _originalScaleFactor = 1.0;
    private const double _wheelSpeed = 0.1;
    private const double _panSpeed = 30;
    // Center of the image.
    private Point ContentCentre = new();
    public ZoomPanel()
    {
        this.GetPropertyChangedObservable(ContentProperty).Subscribe(ContentChanged);
    }
    private void ContentChanged(AvaloniaPropertyChangedEventArgs args)
    {
        if(Content is null) return;
        void Update(AvaloniaPropertyChangedEventArgs? args = null)
        {
            if(OuterCanvas is not null)
            {
                PositionContent();
            }
        }
        Update();
        Content.GetPropertyChangedObservable(Layoutable.WidthProperty).Subscribe(Update);
        Content.GetPropertyChangedObservable(Layoutable.HeightProperty).Subscribe(Update);
    }
    protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
    {
        base.OnApplyTemplate(e);
        OuterCanvas = e.NameScope.Get