Option Strict On
Option Explicit On

Imports System
Imports Nexamas.UI.Components
Imports Nexamas.UI.FloatRuntime
Imports SkiaSharp

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Beginner-facing file explorer facade for MASApplicationWindow.Services.
    ''' Keeps file-explorer float mechanics behind the application entry surface.
    ''' </summary>
    Public NotInheritable Class MASApplicationWindowFileExplorer

        Private Const DefaultOwnerKey As String = "MAS.FileExplorer.Service"
        Private ReadOnly _service As MASFileExplorerService
        Private ReadOnly _throwIfDisposed As Action

        Private ReadOnly Property Service As MASFileExplorerService
            Get
                _throwIfDisposed.Invoke()
                Return _service
            End Get
        End Property

        Friend Sub New(service As MASFileExplorerService, throwIfDisposed As Action)
            If service Is Nothing Then Throw New ArgumentNullException(NameOf(service))
            If throwIfDisposed Is Nothing Then Throw New ArgumentNullException(NameOf(throwIfDisposed))
            _service = service
            _throwIfDisposed = throwIfDisposed
        End Sub

        Public Function ShowComputer(Optional ownerKey As String = DefaultOwnerKey,
                                     Optional onClosed As Action = Nothing,
                                     Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                                     Optional onCancelled As Action = Nothing) As MASApplicationSurfaceHandle

            Return ToCompatibilitySurfaceHandle(
                ShowComputerEx(
                    ownerKey:=ownerKey,
                    onClosed:=onClosed,
                    onAccepted:=onAccepted,
                    onCancelled:=onCancelled))
        End Function

        Friend Function ShowComputerEx(Optional ownerKey As String = DefaultOwnerKey,
                                       Optional onClosed As Action = Nothing,
                                       Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                                       Optional onCancelled As Action = Nothing) As MASApplicationSurfaceShowResult

            Return MASApplicationSurfaceShowResult.FromFloatShowResult(
                Service.ShowComputerEx(
                    ownerKey:=ownerKey,
                    onClosed:=onClosed,
                    onAccepted:=ToApplicationAcceptedCallback(onAccepted),
                    onCancelled:=onCancelled))
        End Function

        Public Function ShowComputer(ownerKey As String,
                                     options As MASApplicationFileExplorerOptions,
                                     Optional onOpened As Action(Of MASApplicationOpenedEventArgs) = Nothing,
                                     Optional onClosed As Action(Of MASApplicationClosedEventArgs) = Nothing,
                                     Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                                     Optional onCancelled As Action = Nothing) As MASApplicationSurfaceHandle

            Return ToCompatibilitySurfaceHandle(
                ShowComputerEx(
                    ownerKey:=ownerKey,
                    options:=options,
                    onOpened:=onOpened,
                    onClosed:=onClosed,
                    onAccepted:=onAccepted,
                    onCancelled:=onCancelled))
        End Function

        Friend Function ShowComputerEx(ownerKey As String,
                                       options As MASApplicationFileExplorerOptions,
                                       Optional onOpened As Action(Of MASApplicationOpenedEventArgs) = Nothing,
                                       Optional onClosed As Action(Of MASApplicationClosedEventArgs) = Nothing,
                                       Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                                       Optional onCancelled As Action = Nothing) As MASApplicationSurfaceShowResult

            Return MASApplicationSurfaceShowResult.FromFloatShowResult(
                Service.ShowComputerEx(
                    ownerKey:=ownerKey,
                    options:=ToFloatOptions(options),
                    onOpened:=ToApplicationOpenedCallback(onOpened),
                    onClosed:=ToApplicationClosedCallback(onClosed, AddressOf ConvertExplorerValue),
                    onAccepted:=ToApplicationAcceptedCallback(onAccepted),
                    onCancelled:=onCancelled))
        End Function

        Public Function Show(options As MASApplicationFileExplorerOptions,
                             Optional ownerKey As String = DefaultOwnerKey,
                             Optional onClosed As Action = Nothing,
                             Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                             Optional onCancelled As Action = Nothing) As MASApplicationSurfaceHandle

            Return ToCompatibilitySurfaceHandle(
                ShowEx(
                    options:=options,
                    ownerKey:=ownerKey,
                    onClosed:=onClosed,
                    onAccepted:=onAccepted,
                    onCancelled:=onCancelled))
        End Function

        Friend Function ShowEx(options As MASApplicationFileExplorerOptions,
                               Optional ownerKey As String = DefaultOwnerKey,
                               Optional onClosed As Action = Nothing,
                               Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                               Optional onCancelled As Action = Nothing) As MASApplicationSurfaceShowResult

            Return MASApplicationSurfaceShowResult.FromFloatShowResult(
                Service.ShowEx(
                    options:=ToFloatOptions(options),
                    ownerKey:=ownerKey,
                    onClosed:=onClosed,
                    onAccepted:=ToApplicationAcceptedCallback(onAccepted),
                    onCancelled:=onCancelled))
        End Function

        Public Function Show(ownerKey As String,
                             options As MASApplicationFileExplorerOptions,
                             Optional onOpened As Action(Of MASApplicationOpenedEventArgs) = Nothing,
                             Optional onClosed As Action(Of MASApplicationClosedEventArgs) = Nothing,
                             Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                             Optional onCancelled As Action = Nothing) As MASApplicationSurfaceHandle

            Return ToCompatibilitySurfaceHandle(
                ShowEx(
                    ownerKey:=ownerKey,
                    options:=options,
                    onOpened:=onOpened,
                    onClosed:=onClosed,
                    onAccepted:=onAccepted,
                    onCancelled:=onCancelled))
        End Function

        Friend Function ShowEx(ownerKey As String,
                               options As MASApplicationFileExplorerOptions,
                               Optional onOpened As Action(Of MASApplicationOpenedEventArgs) = Nothing,
                               Optional onClosed As Action(Of MASApplicationClosedEventArgs) = Nothing,
                               Optional onAccepted As Action(Of MASApplicationFileExplorerResult) = Nothing,
                               Optional onCancelled As Action = Nothing) As MASApplicationSurfaceShowResult

            Return MASApplicationSurfaceShowResult.FromFloatShowResult(
                Service.ShowEx(
                    ownerKey:=ownerKey,
                    options:=ToFloatOptions(options),
                    onOpened:=ToApplicationOpenedCallback(onOpened),
                    onClosed:=ToApplicationClosedCallback(onClosed, AddressOf ConvertExplorerValue),
                    onAccepted:=ToApplicationAcceptedCallback(onAccepted),
                    onCancelled:=onCancelled))
        End Function

        Public Function ShowExplorer(explorer As MASFileExplorerView,
                                     Optional ownerKey As String = DefaultOwnerKey,
                                     Optional onClosed As Action = Nothing) As MASApplicationSurfaceHandle

            Return ToCompatibilitySurfaceHandle(ShowExplorerEx(explorer, ownerKey, onClosed))
        End Function

        Friend Function ShowExplorerEx(explorer As MASFileExplorerView,
                                       Optional ownerKey As String = DefaultOwnerKey,
                                       Optional onClosed As Action = Nothing) As MASApplicationSurfaceShowResult

            Return MASApplicationSurfaceShowResult.FromFloatShowResult(
                Service.ShowExplorerEx(explorer, ownerKey, onClosed))
        End Function

        Public Function IsOpen(handle As MASApplicationSurfaceHandle) As Boolean
            If handle Is Nothing Then Return False
            Return Service.IsOpen(handle.FloatHandleCore)
        End Function

        Public Sub Close(handle As MASApplicationSurfaceHandle,
                         Optional reason As MASApplicationCloseReason = MASApplicationCloseReason.Programmatic)

            If handle Is Nothing Then Return
            Service.Close(handle.FloatHandleCore, MASApplicationSurfaceContractMapper.ToFloatCloseReason(reason))
        End Sub

        Public Sub CloseByOwner(ownerKey As String,
                                Optional reason As MASApplicationCloseReason = MASApplicationCloseReason.Programmatic)

            Service.CloseByOwner(ownerKey, MASApplicationSurfaceContractMapper.ToFloatCloseReason(reason))
        End Sub

        Friend Function GetDefaultExplorerBoundsPx() As SKRect
            Return Service.GetDefaultExplorerBoundsPx()
        End Function

        Friend Function GetDefaultExplorerBoundsPx(availableBoundsPx As SKRect) As SKRect
            Return Service.GetDefaultExplorerBoundsPx(availableBoundsPx)
        End Function

        Private Shared Function ToFloatOptions(options As MASApplicationFileExplorerOptions) As MASFileExplorerFloatOptions
            If options Is Nothing Then Return MASFileExplorerFloatOptions.CreateDefault()
            Return options.ToFloatOptions()
        End Function

        Private Shared Function ToApplicationOpenedCallback(onOpened As Action(Of MASApplicationOpenedEventArgs)) As Action(Of MASFloatHandle)
            If onOpened Is Nothing Then Return Nothing

            Return Sub(handle As MASFloatHandle)
                       Dim args As MASApplicationOpenedEventArgs = MASApplicationOpenedEventArgs.FromFloatHandle(handle)
                       If args IsNot Nothing Then onOpened.Invoke(args)
                   End Sub
        End Function

        Private Shared Function ToApplicationClosedCallback(onClosed As Action(Of MASApplicationClosedEventArgs),
                                                            Optional valueConverter As Func(Of Object, Object) = Nothing) As Action(Of MASFloatClosedEventArgs)
            If onClosed Is Nothing Then Return Nothing

            Return Sub(args As MASFloatClosedEventArgs)
                       onClosed.Invoke(MASApplicationClosedEventArgs.FromFloatEventArgs(args, valueConverter))
                   End Sub
        End Function

        Private Shared Function ToApplicationAcceptedCallback(onAccepted As Action(Of MASApplicationFileExplorerResult)) As Action(Of MASFileExplorerFloatResult)
            If onAccepted Is Nothing Then Return Nothing

            Return Sub(result As MASFileExplorerFloatResult)
                       onAccepted.Invoke(MASApplicationFileExplorerResult.FromFloatResult(result))
                   End Sub
        End Function

        Private Shared Function ConvertExplorerValue(value As Object) As Object
            Dim explorerResult As MASFileExplorerFloatResult = TryCast(value, MASFileExplorerFloatResult)
            If explorerResult Is Nothing Then Return value
            Return MASApplicationFileExplorerResult.FromFloatResult(explorerResult)
        End Function

        Private Shared Function ToCompatibilitySurfaceHandle(result As MASApplicationSurfaceShowResult) As MASApplicationSurfaceHandle
            If result Is Nothing Then Return Nothing

            If result.Status = MASApplicationSurfaceShowStatus.Rejected Then
                Throw New InvalidOperationException("Application surface show rejected: " & result.Reason)
            End If

            Return result.Handle
        End Function

        ''' <summary>
        ''' Advanced compatibility access to the underlying RootHost-backed file explorer service.
        ''' Prefer the methods on MASApplicationWindow.Services.FileExplorer for normal SDK code.
        ''' </summary>
        <Obsolete("AdvancedService is a internal advanced compatibility hook. Prefer MASApplicationWindow.Services.FileExplorer intent-level methods for new SDK code.", True)>
        Friend ReadOnly Property AdvancedService As MASFileExplorerService
            Get
                Return _service
            End Get
        End Property

    End Class

End Namespace
