Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Collections.ObjectModel
Imports System.Windows.Forms
Imports Nexamas.UI.Architecture
Imports Nexamas.UI.Composition
Imports Nexamas.UI.Controls
Imports Nexamas.UI.General
Imports Nexamas.UI.Icons
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 MASFileDropZone

#Region "Rendering"
        Protected Overrides Sub Render(canvas As SKCanvas,
                                       ctx As MASThemeContext,
                                       pixelBounds As SKRect)
            If canvas Is Nothing OrElse ctx Is Nothing Then Return
            If pixelBounds.Width <= 1.0F OrElse pixelBounds.Height <= 1.0F Then Return

            Dim dpi As Single = PixelSnap.SafeDpi(ctx.Dpi)
            Dim bounds As SKRect = PixelSnap.SnapRect(pixelBounds, dpi)
            If bounds.Width <= 1.0F OrElse bounds.Height <= 1.0F Then Return

            _primitives.DrawCardSurface(canvas, ctx, bounds, dpi, _contract, MASCardVisualStyle.Secondary)
            DrawDropSurface(canvas, ctx, bounds, dpi)
            DrawContent(canvas, ctx, bounds, dpi)
        End Sub

        Private Sub DrawDropSurface(canvas As SKCanvas,
                                    ctx As MASThemeContext,
                                    bounds As SKRect,
                                    dpi As Single)
            Dim padding As Single = FileDropZoneTokens.PaddingDip * dpi
            _dropRect = PixelSnap.SnapRect(New SKRect(bounds.Left + padding,
                                                      bounds.Top + padding,
                                                      bounds.Right - padding,
                                                      bounds.Bottom - padding), dpi)
            If _dropRect.Width <= 1.0F OrElse _dropRect.Height <= 1.0F Then Return

            Dim accent As SKColor = MASFileDropZonePolicy.ResolveAccentColor(ctx)
            Dim danger As SKColor = MASFileDropZonePolicy.ResolveRejectedColor(ctx)
            Dim borderColor As SKColor = If(_lastRejectedReason.Length > 0, danger, accent)
            Dim borderAlpha As Byte = If(_lastRejectedReason.Length > 0,
                                         FileDropZoneTokens.BorderRejectedAlpha,
                                         If(_hoverBrowse OrElse _pressedBrowse,
                                            FileDropZoneTokens.BorderHoverAlpha,
                                            FileDropZoneTokens.BorderAlpha))
            Dim radius As Single = Math.Min(_dropRect.Width, _dropRect.Height) * 0.055F
            radius = Math.Max(12.0F * dpi, Math.Min(24.0F * dpi, radius))

            Using fillPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Fill,
                .Color = accent.WithAlpha(FileDropZoneTokens.DropHaloAlpha)
            }
                canvas.DrawRoundRect(_dropRect, radius, radius, fillPaint)
            End Using

            Using borderPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(1.0F, FileDropZoneTokens.BorderStrokeDip * dpi),
                .Color = borderColor.WithAlpha(borderAlpha),
                .PathEffect = SKPathEffect.CreateDash(New Single() {FileDropZoneTokens.DashLengthDip * dpi, FileDropZoneTokens.DashGapDip * dpi}, 0.0F)
            }
                canvas.DrawRoundRect(_dropRect, radius, radius, borderPaint)
            End Using
        End Sub

        Private Sub DrawContent(canvas As SKCanvas,
                                ctx As MASThemeContext,
                                bounds As SKRect,
                                dpi As Single)
            If ctx.Typography Is Nothing Then Return
            If _dropRect.IsEmpty Then Return

            _rowHits.Clear()

            Dim layout As MASFileDropZonePolicy.FileDropZoneLayout = MASFileDropZonePolicy.ResolveLayout(_dropRect, _rows.Count, dpi)
            If layout.PrimaryRect.Width <= 1.0F OrElse layout.PrimaryRect.Height <= 1.0F Then Return

            Dim isRtl As Boolean = MASFileDropZonePolicy.ResolveRightToLeft()
            Dim accent As SKColor = MASFileDropZonePolicy.ResolveAccentColor(ctx)
            Dim textColor As SKColor = MASFileDropZonePolicy.ResolveTextColor(ctx)
            Dim mutedColor As SKColor = MASFileDropZonePolicy.ResolveMutedTextColor(ctx)
            Dim danger As SKColor = MASFileDropZonePolicy.ResolveRejectedColor(ctx)

            Dim buttonPaint As SKPaint = ctx.Typography.GetPaint(MASTypography.MASTextStyle.Button, textColor)
            If buttonPaint Is Nothing Then Return

            Dim contentGap As Single = If(layout.IsCompact,
                                          FileDropZoneTokens.CompactContentGapDip * dpi,
                                          FileDropZoneTokens.ContentGapDip * dpi)
            Dim iconSize As Single = If(layout.IsCompact,
                                        FileDropZoneTokens.CompactIconSizeDip * dpi,
                                        FileDropZoneTokens.IconSizeDip * dpi)
            Dim titleHeight As Single = FileDropZoneTokens.SummaryHeightDip * dpi
            Dim descriptionHeight As Single = If(layout.PrimaryRect.Height >= 122.0F * dpi, FileDropZoneTokens.SummaryHeightDip * dpi, 0.0F)
            Dim extensionsHeight As Single = If(layout.PrimaryRect.Height >= 162.0F * dpi AndAlso layout.PrimaryRect.Width >= 360.0F * dpi, 18.0F * dpi, 0.0F)
            Dim statusHeight As Single = If(Not layout.HasPreview OrElse layout.PrimaryRect.Height >= 176.0F * dpi, 18.0F * dpi, 0.0F)
            Dim buttonHeight As Single = FileDropZoneTokens.ButtonHeightDip * dpi

            Dim groupHeight As Single = iconSize + contentGap + titleHeight + descriptionHeight + extensionsHeight + contentGap + buttonHeight
            If statusHeight > 0.0F Then groupHeight += contentGap + statusHeight

            Dim y As Single = layout.PrimaryRect.MidY - groupHeight * 0.5F
            If y < layout.PrimaryRect.Top Then y = layout.PrimaryRect.Top
            If y + groupHeight > layout.PrimaryRect.Bottom Then y = Math.Max(layout.PrimaryRect.Top, layout.PrimaryRect.Bottom - groupHeight)

            Dim centerX As Single = layout.PrimaryRect.MidX
            Dim iconRect As New SKRect(centerX - iconSize * 0.5F, y, centerX + iconSize * 0.5F, y + iconSize)
            MASIconPainter.Draw(canvas, PixelSnap.SnapRect(iconRect, dpi), dpi, MASIconKind.Upload, accent.WithAlpha(220), MASIconStyle.Outline)
            y = iconRect.Bottom + contentGap

            Dim horizontalTextInset As Single = Math.Max(8.0F * dpi, layout.PrimaryRect.Width * 0.08F)
            Dim textRect As New SKRect(layout.PrimaryRect.Left + horizontalTextInset, y, layout.PrimaryRect.Right - horizontalTextInset, y + titleHeight)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, _title, textRect, dpi, MASTypography.MASTextStyle.Title, textColor, TypographyTextPrimitives.TextAlign.Center, False)
            y += titleHeight

            If descriptionHeight > 0.0F Then
                textRect = New SKRect(layout.PrimaryRect.Left + horizontalTextInset, y, layout.PrimaryRect.Right - horizontalTextInset, y + descriptionHeight)
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, _description, textRect, dpi, MASTypography.MASTextStyle.Body, mutedColor, TypographyTextPrimitives.TextAlign.Center, False)
                y += descriptionHeight
            End If

            If extensionsHeight > 0.0F Then
                textRect = New SKRect(layout.PrimaryRect.Left + horizontalTextInset, y, layout.PrimaryRect.Right - horizontalTextInset, y + extensionsHeight)
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, AllowedExtensionsText, textRect, dpi, MASTypography.MASTextStyle.Micro, mutedColor.WithAlpha(145), TypographyTextPrimitives.TextAlign.Center, False)
                y += extensionsHeight
            End If

            y += contentGap
            Dim buttonWidth As Single = ResolveBrowseButtonWidth(buttonPaint, dpi)
            Dim buttonRect As New SKRect(centerX - buttonWidth * 0.5F, y, centerX + buttonWidth * 0.5F, y + buttonHeight)
            DrawBrowseButton(canvas, ctx, PixelSnap.SnapRect(buttonRect, dpi), dpi, buttonPaint)
            y = _browseRect.Bottom

            If statusHeight > 0.0F Then
                y += contentGap
                Dim statusText As String = MASFileDropZonePolicy.BuildSummaryText(_acceptedPaths.Count, _lastRejectedReason)
                Dim statusColor As SKColor = If(_lastRejectedReason.Length > 0, danger, mutedColor)
                Dim statusRect As New SKRect(layout.PrimaryRect.Left + horizontalTextInset, y, layout.PrimaryRect.Right - horizontalTextInset, y + statusHeight)
                TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, statusText, statusRect, dpi, MASTypography.MASTextStyle.Micro, statusColor, TypographyTextPrimitives.TextAlign.Center, False)
            End If

            If layout.HasPreview Then
                DrawRows(canvas, ctx, layout.PreviewRect, layout.RowCapacity, dpi, isRtl)
            End If
        End Sub

        Private Function ResolveBrowseButtonWidth(buttonTextPaint As SKPaint,
                                                  dpi As Single) As Single
            Dim measured As Single = If(buttonTextPaint Is Nothing, 0.0F, buttonTextPaint.MeasureText(_browseActionText))
            Return Math.Max(FileDropZoneTokens.ButtonMinWidthDip * dpi, measured + 28.0F * dpi)
        End Function

        Private Sub DrawBrowseButton(canvas As SKCanvas,
                                     ctx As MASThemeContext,
                                     rect As SKRect,
                                     dpi As Single,
                                     buttonTextPaint As SKPaint)
            _browseRect = rect
            If _browseRect.Width <= 1.0F OrElse _browseRect.Height <= 1.0F Then Return

            Dim alpha As Byte = FileDropZoneTokens.ButtonAlpha
            If _pressedBrowse Then
                alpha = FileDropZoneTokens.ButtonPressedAlpha
            ElseIf _hoverBrowse Then
                alpha = FileDropZoneTokens.ButtonHoverAlpha
            End If

            Dim accent As SKColor = MASFileDropZonePolicy.ResolveAccentColor(ctx)
            Dim radius As Single = Math.Min(_browseRect.Height * 0.5F, FileDropZoneTokens.ButtonRadiusDip * dpi)
            Using fillPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Fill,
                .Color = accent.WithAlpha(alpha)
            }
                canvas.DrawRoundRect(_browseRect, radius, radius, fillPaint)
            End Using

            Using borderPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(1.0F, dpi),
                .Color = accent.WithAlpha(90)
            }
                canvas.DrawRoundRect(_browseRect, radius, radius, borderPaint)
            End Using

            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, _browseActionText, _browseRect, dpi, MASTypography.MASTextStyle.Button, MASFileDropZonePolicy.ResolveTextColor(ctx), TypographyTextPrimitives.TextAlign.Center, False)
        End Sub
#End Region

    End Class

End Namespace
