Option Strict On
Option Explicit On

Imports System.Collections.Generic
Imports SkiaSharp

Namespace Nexamas.UI.Components

    Friend NotInheritable Class MessageBoxRequestBuilder

        Private ReadOnly _request As MessageBoxRequest

        Private Sub New(kind As MessageBoxKind)
            _request = New MessageBoxRequest()
            _request.Kind = kind
        End Sub

        Friend Shared Function Create(Optional kind As MessageBoxKind = MessageBoxKind.Information) As MessageBoxRequestBuilder
            Return New MessageBoxRequestBuilder(kind)
        End Function

        Friend Function WithTitle(value As String) As MessageBoxRequestBuilder
            _request.Title = If(value, String.Empty)
            Return Me
        End Function

        Friend Function WithMessage(value As String) As MessageBoxRequestBuilder
            _request.Message = If(value, String.Empty)
            Return Me
        End Function

        Friend Function WithDetail(value As String) As MessageBoxRequestBuilder
            _request.Detail = If(value, String.Empty)
            Return Me
        End Function

        Friend Function WithKind(value As MessageBoxKind) As MessageBoxRequestBuilder
            _request.Kind = value
            Return Me
        End Function

        Friend Function WithButtons(buttons As IReadOnlyList(Of MASButtonSpec)) As MessageBoxRequestBuilder
            _request.Buttons = buttons
            _request.ButtonResults = ResolveDefaultResultsForButtons(buttons)
            Return Me
        End Function

        Friend Function WithButtonResults(results As IReadOnlyList(Of MessageBoxResult)) As MessageBoxRequestBuilder
            _request.ButtonResults = results
            Return Me
        End Function

        Friend Function WithButtonsAndResults(buttons As IReadOnlyList(Of MASButtonSpec),
                                              results As IReadOnlyList(Of MessageBoxResult)) As MessageBoxRequestBuilder

            _request.Buttons = buttons
            _request.ButtonResults = results
            Return Me

        End Function

        Friend Function WithDefaultResult(value As MessageBoxResult) As MessageBoxRequestBuilder
            _request.DefaultResult = value
            Return Me
        End Function

        Friend Function WithEscapeResult(value As MessageBoxResult) As MessageBoxRequestBuilder
            _request.EscapeResult = value
            Return Me
        End Function

        Friend Function WithCloseButton(enabled As Boolean) As MessageBoxRequestBuilder
            _request.AllowCloseButton = enabled
            Return Me
        End Function

        Friend Function WithBackdropDismiss(enabled As Boolean) As MessageBoxRequestBuilder
            _request.AllowBackdropDismiss = enabled
            Return Me
        End Function

        Friend Function WithMetrics(metrics As MessageBoxMetrics) As MessageBoxRequestBuilder
            _request.MetricsOverride = metrics
            Return Me
        End Function

        Friend Function WithCompanyIconNone() As MessageBoxRequestBuilder

            If _request.CompanyIcon Is Nothing Then
                _request.CompanyIcon = New MessageBoxCompanyIconSpec()
            End If

            _request.CompanyIcon.Mode = MessageBoxCompanyIconMode.None
            _request.CompanyIcon.Image = Nothing
            _request.CompanyIcon.FallbackText = String.Empty

            Return Me

        End Function

        Friend Function WithReservedCompanyIcon() As MessageBoxRequestBuilder

            If _request.CompanyIcon Is Nothing Then
                _request.CompanyIcon = New MessageBoxCompanyIconSpec()
            End If

            _request.CompanyIcon.Mode = MessageBoxCompanyIconMode.ReserveSpace
            _request.CompanyIcon.Image = Nothing
            _request.CompanyIcon.FallbackText = String.Empty

            Return Me

        End Function

        Friend Function WithCompanyIconFallback(text As String) As MessageBoxRequestBuilder

            If _request.CompanyIcon Is Nothing Then
                _request.CompanyIcon = New MessageBoxCompanyIconSpec()
            End If

            _request.CompanyIcon.Mode = MessageBoxCompanyIconMode.ShowFallback
            _request.CompanyIcon.FallbackText = If(text, String.Empty)
            _request.CompanyIcon.Image = Nothing

            Return Me

        End Function

        Friend Function WithCompanyIconImage(image As SKImage) As MessageBoxRequestBuilder

            If _request.CompanyIcon Is Nothing Then
                _request.CompanyIcon = New MessageBoxCompanyIconSpec()
            End If

            If image Is Nothing Then
                _request.CompanyIcon.Mode = MessageBoxCompanyIconMode.None
            Else
                _request.CompanyIcon.Mode = MessageBoxCompanyIconMode.ShowImage
            End If

            _request.CompanyIcon.Image = image
            _request.CompanyIcon.FallbackText = String.Empty

            Return Me

        End Function

        Friend Function WithCheckBox(text As String,
                                     Optional isChecked As Boolean = False) As MessageBoxRequestBuilder

            _request.ShowCheckBox = True
            _request.CheckBoxText = If(text, String.Empty)
            _request.CheckBoxChecked = isChecked

            Return Me

        End Function

        Friend Function WithoutCheckBox() As MessageBoxRequestBuilder

            _request.ShowCheckBox = False
            _request.CheckBoxText = String.Empty
            _request.CheckBoxChecked = False

            Return Me

        End Function

        Friend Function WithButtonsOK() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.OK()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.OK
            }
            _request.DefaultResult = MessageBoxResult.OK
            _request.EscapeResult = MessageBoxResult.OK

            Return Me

        End Function

        Friend Function WithButtonsOKCancel() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.OKCancel()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.OK,
                MessageBoxResult.Cancel
            }
            _request.DefaultResult = MessageBoxResult.OK
            _request.EscapeResult = MessageBoxResult.Cancel

            Return Me

        End Function

        Friend Function WithButtonsYesNo() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.YesNo()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.Yes,
                MessageBoxResult.No
            }
            _request.DefaultResult = MessageBoxResult.Yes
            _request.EscapeResult = MessageBoxResult.No

            Return Me

        End Function

        Friend Function WithButtonsYesNoCancel() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.YesNoCancel()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.Yes,
                MessageBoxResult.No,
                MessageBoxResult.Cancel
            }
            _request.DefaultResult = MessageBoxResult.Yes
            _request.EscapeResult = MessageBoxResult.Cancel

            Return Me

        End Function

        Friend Function WithRetryCancel() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.RetryCancel()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.Retry,
                MessageBoxResult.Cancel
            }
            _request.DefaultResult = MessageBoxResult.Retry
            _request.EscapeResult = MessageBoxResult.Cancel

            Return Me

        End Function

        Friend Function WithDeleteCancel() As MessageBoxRequestBuilder

            _request.Buttons = MessageBoxPresets.DeleteCancel()
            _request.ButtonResults = New List(Of MessageBoxResult) From {
                MessageBoxResult.OK,
                MessageBoxResult.Cancel
            }
            _request.DefaultResult = MessageBoxResult.OK
            _request.EscapeResult = MessageBoxResult.Cancel

            Return Me

        End Function

        Friend Function Build() As MessageBoxRequest

            NormalizeRequest(_request)
            Return _request

        End Function

        Private Shared Sub NormalizeRequest(request As MessageBoxRequest)

            If request Is Nothing Then Return

            request.Title = If(request.Title, String.Empty)
            request.Message = If(request.Message, String.Empty)
            request.Detail = If(request.Detail, String.Empty)

            If request.Buttons Is Nothing OrElse request.Buttons.Count = 0 Then
                request.Buttons = MessageBoxPresets.OK()
            End If

            If request.ButtonResults Is Nothing OrElse request.ButtonResults.Count <> request.Buttons.Count Then
                request.ButtonResults = ResolveDefaultResultsForButtons(request.Buttons)
            End If

            If request.DefaultResult = MessageBoxResult.None Then
                request.DefaultResult = ResolveFirstNonNoneResult(request.ButtonResults, MessageBoxResult.OK)
            End If

            If request.EscapeResult = MessageBoxResult.None Then
                request.EscapeResult = MessageBoxResult.Close
            End If

            If request.CompanyIcon Is Nothing Then
                request.CompanyIcon = New MessageBoxCompanyIconSpec()
            End If

            request.CheckBoxText = If(request.CheckBoxText, String.Empty)

            If Not request.ShowCheckBox Then
                request.CheckBoxChecked = False
            End If

        End Sub

        Private Shared Function ResolveDefaultResultsForButtons(buttons As IReadOnlyList(Of MASButtonSpec)) As IReadOnlyList(Of MessageBoxResult)

            Dim results As New List(Of MessageBoxResult)()

            If buttons Is Nothing OrElse buttons.Count = 0 Then
                results.Add(MessageBoxResult.OK)
                Return results
            End If

            For i As Integer = 0 To buttons.Count - 1
                results.Add(MessageBoxResultResolver.Resolve(Nothing, buttons(i), i))
            Next

            Return results

        End Function

        Private Shared Function ResolveFirstNonNoneResult(results As IReadOnlyList(Of MessageBoxResult),
                                                         fallback As MessageBoxResult) As MessageBoxResult

            If results IsNot Nothing Then
                For Each item As MessageBoxResult In results
                    If item <> MessageBoxResult.None Then
                        Return item
                    End If
                Next
            End If

            Return fallback

        End Function

    End Class

End Namespace