Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports System.IO
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Layout
Imports Nexamas.UI.Rendering
Imports Nexamas.UI.TextRendering
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Partial Public NotInheritable Class MASImageViewer
#Region "View State API"

        Public Function ZoomIn() As MASImageViewer
            _fitMode = False
            SetZoomInternal(_zoom * ImageViewerTokens.ZoomStep, True)
            Return Me
        End Function

        Public Function ZoomOut() As MASImageViewer
            _fitMode = False
            SetZoomInternal(_zoom / ImageViewerTokens.ZoomStep, True)
            Return Me
        End Function

        Public Function FitToView() As MASImageViewer
            _fitMode = True
            _zoom = ResolveFitZoom()
            _panX = 0.0F
            _panY = 0.0F
            RaiseViewChangedSafe()
            InvalidateVisual()
            Return Me
        End Function

        Public Function ActualSize() As MASImageViewer
            _fitMode = False
            _zoom = MASImageViewerVisualPolicy.NormalizeZoom(1.0F, ImageViewerTokens.MinUsefulScale, ImageViewerTokens.MaxZoom)
            _panX = 0.0F
            _panY = 0.0F
            ClampPanToViewport()
            RaiseViewChangedSafe()
            InvalidateVisual()
            Return Me
        End Function

        Public Function RotateLeft() As MASImageViewer
            RotationDegrees = _rotationDegrees - 90
            Return Me
        End Function

        Public Function RotateRight() As MASImageViewer
            RotationDegrees = _rotationDegrees + 90
            Return Me
        End Function

        Public Function FlipHorizontal() As MASImageViewer
            FlippedHorizontal = Not _flippedHorizontal
            Return Me
        End Function

        Public Function FlipVertical() As MASImageViewer
            FlippedVertical = Not _flippedVertical
            Return Me
        End Function

        Public Function ResetView() As MASImageViewer
            ResetViewCore(True)
            Return Me
        End Function

#End Region

#Region "View State Helpers"

        Private Sub SetZoomInternal(value As Single,
                                    raiseEvents As Boolean)
            Dim normalized As Single = MASImageViewerVisualPolicy.NormalizeZoom(value, ResolveFitZoom(), ImageViewerTokens.MaxZoom)
            If Math.Abs(_zoom - normalized) < 0.0001F Then Return
            _zoom = normalized
            If _zoom <= ResolveFitZoom() + 0.0001F Then
                _fitMode = True
                _panX = 0.0F
                _panY = 0.0F
            Else
                ClampPanToViewport()
            End If
            If raiseEvents Then RaiseViewChangedSafe()
            InvalidateVisual()
        End Sub

        Private Sub SetZoomAroundPoint(value As Single,
                                       anchorPx As SKPoint,
                                       raiseEvents As Boolean)
            Dim oldZoom As Single = _zoom
            Dim normalized As Single = MASImageViewerVisualPolicy.NormalizeZoom(value, ResolveFitZoom(), ImageViewerTokens.MaxZoom)
            If Math.Abs(_zoom - normalized) < 0.0001F Then Return

            _fitMode = False
            If _lastContentRect.Width > 1.0F AndAlso _lastContentRect.Height > 1.0F Then
                MASImageViewerViewportGeometry.ApplyCursorAnchoredZoom(_lastContentRect, anchorPx, oldZoom, normalized, _panX, _panY)
            End If
            _zoom = normalized

            If _zoom <= ResolveFitZoom() + 0.0001F Then
                _fitMode = True
                _panX = 0.0F
                _panY = 0.0F
            Else
                ClampPanToViewport()
            End If

            If raiseEvents Then RaiseViewChangedSafe()
            InvalidateVisual()
        End Sub

        Private Function ResolveFitZoom() As Single
            If _lastContentRect.Width > 1.0F AndAlso _lastContentRect.Height > 1.0F Then Return ResolveFitZoomForRect(_lastContentRect)
            Return _lastFitZoom
        End Function

        Private Function ResolveFitZoomForRect(rect As SKRect) As Single
            If Not HasImage OrElse rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return ImageViewerTokens.DefaultZoom
            Return MASImageViewerViewportGeometry.ResolveFitZoom(rect, _bitmap.Width, _bitmap.Height, _rotationDegrees, _imageFitMode)
        End Function

        Private Function CanPanCurrentView() As Boolean
            If Not HasImage Then Return False
            If _fitMode Then Return False
            Return MASImageViewerViewportGeometry.CanPan(_lastContentRect, _bitmap.Width, _bitmap.Height, _rotationDegrees, _zoom)
        End Function

        Private Sub PanBy(dx As Single,
                          dy As Single)
            If Not CanPanCurrentView() Then Return
            _fitMode = False
            _panX += dx
            _panY += dy
            ClampPanToViewport()
            RaiseViewChangedSafe()
            InvalidateVisual()
        End Sub

        Private Sub ClampPanToViewport()
            If Not HasImage OrElse _lastContentRect.Width <= 1.0F OrElse _lastContentRect.Height <= 1.0F Then
                _panX = 0.0F
                _panY = 0.0F
                Return
            End If

            MASImageViewerViewportGeometry.ClampPan(_lastContentRect, _bitmap.Width, _bitmap.Height, _rotationDegrees, _zoom, _panX, _panY)
        End Sub

        Private Sub ResetViewCore(raiseEvents As Boolean)
            _rotationDegrees = 0
            _flippedHorizontal = False
            _flippedVertical = False
            _panX = 0.0F
            _panY = 0.0F
            _fitMode = True
            _zoom = ResolveFitZoom()
            ClearInteractionState()
            If raiseEvents Then RaiseViewChangedSafe()
            InvalidateVisual()
        End Sub

        Private Sub ClearInteractionState()
            _hoverAction = ImageViewerAction.None
            _pressedAction = ImageViewerAction.None
            _draggingPan = False
            If _chromeMode = MASImageViewerChromeMode.AutoHide Then _chromeHot = False
        End Sub

#End Region

    End Class

End Namespace
