Option Strict On
Option Explicit On

Imports System
Imports System.Collections.Generic
Imports System.Linq

Namespace Nexamas.UI.FileSystem

    ''' <summary>
    ''' Defines the configuration used to create a file picker experience.
    ''' </summary>
    ''' <remarks>
    ''' MASFilePickerOptions is pure data.
    '''
    ''' It does not know about Overlay.
    ''' It does not know about Float.
    ''' It does not close anything.
    ''' It does not own modal/shield behavior.
    '''
    ''' A host may use these options to configure a MASFilePickerControl,
    ''' but host lifetime remains outside this class.
    ''' </remarks>
    Public NotInheritable Class MASFilePickerOptions

        Public Property Mode As MASFilePickerMode = MASFilePickerMode.OpenFile

        Public Property Title As String = "Select file"
        Public Property InitialPath As String = String.Empty
        Public Property FileName As String = String.Empty

        Public Property AllowMultiSelect As Boolean = False
        Public Property ShowHidden As Boolean = False

        Public Property Filter As String = "*.*"

        Public Property ConfirmOverwrite As Boolean = True
        Public Property PrimaryButtonTextOverride As String = String.Empty

        Public Property TargetKinds As MASFileSystemSelectionKinds =
            MASFileSystemSelectionKinds.Folder Or MASFileSystemSelectionKinds.Drive

        Public Property AcceptCurrentPathWhenNoSelection As Boolean = False

        Public Property FooterText As String = String.Empty

#Region "Factory helpers"

        ''' <summary>
        ''' Creates normalized options for opening one or more files.
        ''' This is the public SDK entry point; FilePickerOptionsFactory is now an internal implementation helper.
        ''' </summary>
        Public Shared Function OpenFile(Optional title As String = "Open File",
                                        Optional initialPath As String = "",
                                        Optional filter As String = "*.*",
                                        Optional showHidden As Boolean = False,
                                        Optional allowMultiSelect As Boolean = False,
                                        Optional footerText As String = "",
                                        Optional primaryButtonText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.OpenFile(
                title:=title,
                initialPath:=initialPath,
                filter:=filter,
                showHidden:=showHidden,
                allowMultiSelect:=allowMultiSelect,
                footerText:=footerText,
                primaryButtonText:=primaryButtonText)
        End Function

        ''' <summary>
        ''' Creates normalized options for saving a file.
        ''' </summary>
        Public Shared Function SaveFile(Optional title As String = "Save File",
                                        Optional initialPath As String = "",
                                        Optional filter As String = "*.*",
                                        Optional fileName As String = "",
                                        Optional confirmOverwrite As Boolean = True,
                                        Optional showHidden As Boolean = False,
                                        Optional primaryButtonText As String = "",
                                        Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.SaveFile(
                title:=title,
                initialPath:=initialPath,
                filter:=filter,
                fileName:=fileName,
                confirmOverwrite:=confirmOverwrite,
                showHidden:=showHidden,
                primaryButtonText:=primaryButtonText,
                footerText:=footerText)
        End Function

        ''' <summary>
        ''' Creates normalized options for selecting a single folder.
        ''' </summary>
        Public Shared Function FolderPicker(Optional title As String = "Select Folder",
                                            Optional initialPath As String = "",
                                            Optional showHidden As Boolean = False,
                                            Optional primaryButtonText As String = "",
                                            Optional acceptCurrentPathWhenNoSelection As Boolean = False,
                                            Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.FolderPicker(
                title:=title,
                initialPath:=initialPath,
                showHidden:=showHidden,
                primaryButtonText:=primaryButtonText,
                acceptCurrentPathWhenNoSelection:=acceptCurrentPathWhenNoSelection,
                footerText:=footerText)
        End Function

        ''' <summary>
        ''' Creates normalized options for selecting multiple folders.
        ''' </summary>
        Public Shared Function MultiFolderPicker(Optional title As String = "Select Folders",
                                                 Optional initialPath As String = "",
                                                 Optional showHidden As Boolean = False,
                                                 Optional primaryButtonText As String = "",
                                                 Optional acceptCurrentPathWhenNoSelection As Boolean = False,
                                                 Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.MultiFolderPicker(
                title:=title,
                initialPath:=initialPath,
                showHidden:=showHidden,
                primaryButtonText:=primaryButtonText,
                acceptCurrentPathWhenNoSelection:=acceptCurrentPathWhenNoSelection,
                footerText:=footerText)
        End Function

        ''' <summary>
        ''' Creates normalized options for selecting one or more drives.
        ''' </summary>
        Public Shared Function DrivePicker(Optional title As String = "Select Drive",
                                           Optional initialPath As String = "",
                                           Optional showHidden As Boolean = False,
                                           Optional allowMultiSelect As Boolean = False,
                                           Optional primaryButtonText As String = "",
                                           Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.DrivePicker(
                title:=title,
                initialPath:=initialPath,
                showHidden:=showHidden,
                allowMultiSelect:=allowMultiSelect,
                primaryButtonText:=primaryButtonText,
                footerText:=footerText)
        End Function

        ''' <summary>
        ''' Creates normalized options for selecting folders and drives.
        ''' </summary>
        Public Shared Function FolderAndDrivePicker(Optional title As String = "Select Targets",
                                                    Optional initialPath As String = "",
                                                    Optional showHidden As Boolean = False,
                                                    Optional allowMultiSelect As Boolean = True,
                                                    Optional primaryButtonText As String = "",
                                                    Optional acceptCurrentPathWhenNoSelection As Boolean = False,
                                                    Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.FolderAndDrivePicker(
                title:=title,
                initialPath:=initialPath,
                showHidden:=showHidden,
                allowMultiSelect:=allowMultiSelect,
                primaryButtonText:=primaryButtonText,
                acceptCurrentPathWhenNoSelection:=acceptCurrentPathWhenNoSelection,
                footerText:=footerText)
        End Function

        ''' <summary>
        ''' Creates normalized options for selecting file-system targets by kind.
        ''' </summary>
        Public Shared Function TargetsPicker(targetKinds As MASFileSystemSelectionKinds,
                                             Optional title As String = "Select Targets",
                                             Optional initialPath As String = "",
                                             Optional showHidden As Boolean = False,
                                             Optional allowMultiSelect As Boolean = False,
                                             Optional primaryButtonText As String = "",
                                             Optional acceptCurrentPathWhenNoSelection As Boolean = False,
                                             Optional footerText As String = "") As MASFilePickerOptions
            Return FilePickerOptionsFactory.TargetsPicker(
                targetKinds:=targetKinds,
                title:=title,
                initialPath:=initialPath,
                showHidden:=showHidden,
                allowMultiSelect:=allowMultiSelect,
                primaryButtonText:=primaryButtonText,
                acceptCurrentPathWhenNoSelection:=acceptCurrentPathWhenNoSelection,
                footerText:=footerText)
        End Function

#End Region

        Public Function Clone() As MASFilePickerOptions
            Dim result As New MASFilePickerOptions() With {
                .Mode = Me.Mode,
                .Title = If(Me.Title, String.Empty),
                .InitialPath = If(Me.InitialPath, String.Empty),
                .FileName = If(Me.FileName, String.Empty),
                .AllowMultiSelect = Me.AllowMultiSelect,
                .ShowHidden = Me.ShowHidden,
                .Filter = NormalizeFilter(Me.Filter),
                .ConfirmOverwrite = Me.ConfirmOverwrite,
                .PrimaryButtonTextOverride = If(Me.PrimaryButtonTextOverride, String.Empty),
                .TargetKinds = Me.TargetKinds,
                .AcceptCurrentPathWhenNoSelection = Me.AcceptCurrentPathWhenNoSelection,
                .FooterText = If(Me.FooterText, String.Empty)
            }

            result.Normalize()
            Return result
        End Function

        Public Sub Normalize()
            Title = If(Title, String.Empty)
            InitialPath = If(InitialPath, String.Empty)
            FileName = If(FileName, String.Empty)
            Filter = NormalizeFilter(Filter)
            PrimaryButtonTextOverride = If(PrimaryButtonTextOverride, String.Empty)
            FooterText = If(FooterText, String.Empty)

            If TargetKinds = MASFileSystemSelectionKinds.None Then
                TargetKinds = MASFileSystemSelectionKinds.Folder Or MASFileSystemSelectionKinds.Drive
            End If

            Select Case Mode
                Case MASFilePickerMode.OpenFile
                    AcceptCurrentPathWhenNoSelection = False

                Case MASFilePickerMode.SaveFile
                    AllowMultiSelect = False
                    AcceptCurrentPathWhenNoSelection = False

                Case MASFilePickerMode.PickTargets
                    ' TargetKinds remains meaningful only in PickTargets mode.
                    If TargetKinds = MASFileSystemSelectionKinds.None Then
                        TargetKinds = MASFileSystemSelectionKinds.Folder Or MASFileSystemSelectionKinds.Drive
                    End If

                Case Else
                    Mode = MASFilePickerMode.OpenFile
                    AllowMultiSelect = False
                    AcceptCurrentPathWhenNoSelection = False
            End Select
        End Sub

        Friend Shared Function SafeClone(options As MASFilePickerOptions) As MASFilePickerOptions
            Dim result As MASFilePickerOptions =
                If(options Is Nothing, New MASFilePickerOptions(), options.Clone())

            result.Normalize()
            Return result
        End Function

        Friend Shared Function NormalizeFilter(filter As String) As String
            If String.IsNullOrWhiteSpace(filter) Then Return "*.*"

            Dim raw As String = filter.Trim()
            If String.IsNullOrWhiteSpace(raw) Then Return "*.*"

            Dim parts As String() =
                raw.Split(New Char() {";"c}, StringSplitOptions.RemoveEmptyEntries)

            If parts Is Nothing OrElse parts.Length = 0 Then Return "*.*"

            Dim normalized As New List(Of String)()

            For Each part As String In parts
                Dim p As String = If(part, String.Empty).Trim()

                If String.IsNullOrWhiteSpace(p) Then Continue For

                If String.Equals(p, "*", StringComparison.Ordinal) Then
                    p = "*.*"
                End If

                If Not normalized.Contains(p, StringComparer.OrdinalIgnoreCase) Then
                    normalized.Add(p)
                End If
            Next

            If normalized.Count = 0 Then Return "*.*"

            Return String.Join(";", normalized)
        End Function

    End Class

End Namespace