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 / Rows"
        Private Sub DrawRows(canvas As SKCanvas,
                             ctx As MASThemeContext,
                             previewRect As SKRect,
                             rowCapacity As Integer,
                             dpi As Single,
                             isRtl As Boolean)
            _rowHits.Clear()
            If ctx.Typography Is Nothing OrElse _rows.Count = 0 OrElse rowCapacity <= 0 OrElse previewRect.IsEmpty Then Return

            Dim rowHeight As Single = FileDropZoneTokens.RowHeightDip * dpi
            Dim rowGap As Single = FileDropZoneTokens.RowGapDip * dpi
            Dim shown As Integer = Math.Min(rowCapacity, _rows.Count)
            If shown <= 0 Then Return

            Dim hiddenCount As Integer = Math.Max(0, _rows.Count - shown)
            Dim y As Single = previewRect.Top
            If hiddenCount > 0 AndAlso shown > 1 Then
                DrawOverflowRow(canvas, ctx, previewRect, y, hiddenCount, dpi, isRtl)
                y += rowHeight + rowGap
                shown -= 1
            End If

            Dim startIndex As Integer = Math.Max(0, _rows.Count - shown)
            For i As Integer = 0 To shown - 1
                Dim rowIndex As Integer = startIndex + i
                If rowIndex < 0 OrElse rowIndex >= _rows.Count Then Continue For
                DrawFileRow(canvas, ctx, previewRect, y, _rows(rowIndex), dpi, isRtl)
                y += rowHeight + rowGap
                If y > previewRect.Bottom + rowGap Then Exit For
            Next
        End Sub

        Private Sub DrawOverflowRow(canvas As SKCanvas,
                                    ctx As MASThemeContext,
                                    previewRect As SKRect,
                                    y As Single,
                                    hiddenCount As Integer,
                                    dpi As Single,
                                    isRtl As Boolean)
            Dim text As String = "+" & hiddenCount.ToString(Global.System.Globalization.CultureInfo.InvariantCulture) & " more"
            DrawPreviewRowSurface(canvas,
                                  PixelSnap.SnapRect(New SKRect(previewRect.Left, y, previewRect.Right, y + FileDropZoneTokens.RowHeightDip * dpi), dpi),
                                  MASFileDropZonePolicy.ResolveMutedTextColor(ctx),
                                  dpi,
                                  False)
            Dim rect As New SKRect(previewRect.Left + FileDropZoneTokens.RowInsetDip * dpi,
                                   y,
                                   previewRect.Right - FileDropZoneTokens.RowInsetDip * dpi,
                                   y + FileDropZoneTokens.RowHeightDip * dpi)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, rect, dpi, MASTypography.MASTextStyle.Micro, MASFileDropZonePolicy.ResolveMutedTextColor(ctx), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
        End Sub

        Private Sub DrawFileRow(canvas As SKCanvas,
                                ctx As MASThemeContext,
                                previewRect As SKRect,
                                y As Single,
                                row As FileDropRow,
                                dpi As Single,
                                isRtl As Boolean)
            Dim rowRect As SKRect = PixelSnap.SnapRect(New SKRect(previewRect.Left,
                                                                  y,
                                                                  previewRect.Right,
                                                                  y + FileDropZoneTokens.RowHeightDip * dpi), dpi)
            If rowRect.Width <= 1.0F OrElse rowRect.Height <= 1.0F Then Return

            Dim accent As SKColor = MASFileDropZonePolicy.ResolveAccentColor(ctx)
            Dim danger As SKColor = MASFileDropZonePolicy.ResolveRejectedColor(ctx)
            Dim muted As SKColor = MASFileDropZonePolicy.ResolveMutedTextColor(ctx)
            Dim tone As SKColor = If(row.Accepted, accent, danger)
            Dim fileIndex As Integer = If(row.Accepted, FindAcceptedPathIndex(row.Path), -1)
            Dim hovered As Boolean = fileIndex >= 0 AndAlso fileIndex = _hoverRemoveIndex
            DrawPreviewRowSurface(canvas, rowRect, tone, dpi, hovered)

            Dim inset As Single = FileDropZoneTokens.RowInsetDip * dpi
            Dim iconSize As Single = FileDropZoneTokens.RowIconSizeDip * dpi
            Dim closeSize As Single = FileDropZoneTokens.RowCloseBoxDip * dpi
            Dim gap As Single = 8.0F * dpi
            Dim iconLeft As Single = If(isRtl, rowRect.Right - inset - iconSize, rowRect.Left + inset)
            Dim iconRect As New SKRect(iconLeft,
                                       rowRect.MidY - iconSize * 0.5F,
                                       iconLeft + iconSize,
                                       rowRect.MidY + iconSize * 0.5F)
            MASIconPainter.Draw(canvas, PixelSnap.SnapRect(iconRect, dpi), dpi, If(row.Accepted, MASIconKind.File, MASIconKind.Warning), tone.WithAlpha(205), MASIconStyle.Outline)

            Dim closeRect As SKRect = SKRect.Empty
            Dim textLeft As Single
            Dim textRight As Single
            If isRtl Then
                textRight = iconRect.Left - gap
                textLeft = rowRect.Left + inset
                If fileIndex >= 0 Then
                    closeRect = PixelSnap.SnapRect(New SKRect(rowRect.Left + inset,
                                                              rowRect.MidY - closeSize * 0.5F,
                                                              rowRect.Left + inset + closeSize,
                                                              rowRect.MidY + closeSize * 0.5F), dpi)
                    textLeft = closeRect.Right + gap
                End If
            Else
                textLeft = iconRect.Right + gap
                textRight = rowRect.Right - inset
                If fileIndex >= 0 Then
                    closeRect = PixelSnap.SnapRect(New SKRect(rowRect.Right - inset - closeSize,
                                                              rowRect.MidY - closeSize * 0.5F,
                                                              rowRect.Right - inset,
                                                              rowRect.MidY + closeSize * 0.5F), dpi)
                    textRight = closeRect.Left - gap
                End If
            End If

            If fileIndex >= 0 Then
                DrawCloseGlyph(canvas, closeRect, dpi, tone, fileIndex = _pressedRemoveIndex, fileIndex = _hoverRemoveIndex)
                _rowHits.Add(New FileDropRowHit(fileIndex, rowRect, closeRect))
            End If

            Dim text As String = MASFileDropZonePolicy.FileName(row.Path)
            If Not row.Accepted AndAlso row.Reason.Length > 0 Then text &= " — " & row.Reason
            Dim textRect As New SKRect(textLeft, rowRect.Top, Math.Max(textLeft, textRight), rowRect.Bottom)
            TypographyTextPrimitives.DrawSingleLineText(canvas, ctx, text, textRect, dpi, MASTypography.MASTextStyle.Micro, If(row.Accepted, muted, danger), If(isRtl, TypographyTextPrimitives.TextAlign.Right, TypographyTextPrimitives.TextAlign.Left), False)
        End Sub

        Private Shared Sub DrawPreviewRowSurface(canvas As SKCanvas,
                                                 rowRect As SKRect,
                                                 tone As SKColor,
                                                 dpi As Single,
                                                 hovered As Boolean)
            Dim radius As Single = FileDropZoneTokens.RowRadiusDip * dpi
            Dim fillAlpha As Byte = If(hovered, FileDropZoneTokens.RowHoverFillAlpha, FileDropZoneTokens.RowFillAlpha)
            Using fillPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Fill,
                .Color = tone.WithAlpha(fillAlpha)
            }
                canvas.DrawRoundRect(rowRect, radius, radius, fillPaint)
            End Using

            Using strokePaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(1.0F, dpi),
                .Color = tone.WithAlpha(FileDropZoneTokens.RowStrokeAlpha)
            }
                canvas.DrawRoundRect(rowRect, radius, radius, strokePaint)
            End Using
        End Sub

        Private Shared Sub DrawCloseGlyph(canvas As SKCanvas,
                                          rect As SKRect,
                                          dpi As Single,
                                          tone As SKColor,
                                          pressed As Boolean,
                                          hovered As Boolean)
            If rect.Width <= 1.0F OrElse rect.Height <= 1.0F Then Return
            Dim fillAlpha As Byte = If(pressed OrElse hovered, FileDropZoneTokens.CloseHoverFillAlpha, FileDropZoneTokens.CloseFillAlpha)
            Using fillPaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Fill,
                .Color = tone.WithAlpha(fillAlpha)
            }
                canvas.DrawOval(rect, fillPaint)
            End Using

            Dim pad As Single = 5.4F * dpi
            Using strokePaint As New SKPaint With {
                .IsAntialias = True,
                .Style = SKPaintStyle.Stroke,
                .StrokeWidth = Math.Max(1.0F, 1.15F * dpi),
                .StrokeCap = SKStrokeCap.Round,
                .Color = tone.WithAlpha(218)
            }
                canvas.DrawLine(rect.Left + pad, rect.Top + pad, rect.Right - pad, rect.Bottom - pad, strokePaint)
                canvas.DrawLine(rect.Right - pad, rect.Top + pad, rect.Left + pad, rect.Bottom - pad, strokePaint)
            End Using
        End Sub
#End Region

    End Class

End Namespace
