Option Strict On
Option Explicit On

Imports System
Imports System.Drawing
Imports System.Globalization
Imports System.IO
Imports System.Text
Imports System.Windows.Forms
Imports Nexamas.UI.RuntimeSettings

Namespace Nexamas.UI.Application

    ''' <summary>
    ''' Internal durable store for MAS host-window presentation preferences.
    ''' It shares MASRuntimeSettingsPathResolver with size-profile persistence and never arranges controls.
    ''' </summary>
    Friend NotInheritable Class MASWindowPresentationStore

        Private Const FolderName As String = "WindowPresentation"
        Private Const FileExtension As String = ".txt"

        Private Sub New()
        End Sub

        Friend Shared Function Load(key As String) As MASWindowPresentationState
            Dim path As String = ResolvePath(key)
            If String.IsNullOrWhiteSpace(path) OrElse Not File.Exists(path) Then Return Nothing

            Try
                Dim state As New MASWindowPresentationState()
                Dim lines As String() = File.ReadAllLines(path, Encoding.UTF8)

                For Each rawLine As String In lines
                    Dim line As String = If(rawLine, String.Empty).Trim()
                    If line.Length = 0 Then Continue For

                    Dim separatorIndex As Integer = line.IndexOf("="c)
                    If separatorIndex <= 0 Then Continue For

                    Dim name As String = line.Substring(0, separatorIndex).Trim()
                    Dim value As String = line.Substring(separatorIndex + 1).Trim()

                    Select Case name.ToUpperInvariant()
                        Case "PROFILEKIND"
                            Dim parsedProfile As MASWindowPresentationProfileKind = MASWindowPresentationProfileKind.Standard
                            If [Enum].TryParse(Of MASWindowPresentationProfileKind)(value, True, parsedProfile) Then
                                state.ProfileKind = parsedProfile
                            End If
                        Case "WINDOWSTATE"
                            Dim parsedState As FormWindowState = FormWindowState.Normal
                            If [Enum].TryParse(Of FormWindowState)(value, True, parsedState) Then
                                state.WindowState = parsedState
                            End If
                        Case "BOUNDS"
                            state.Bounds = ParseBounds(value)
                    End Select
                Next

                If state.HasBounds OrElse state.WindowState = FormWindowState.Maximized Then Return state
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowFileSystemBoundary(masCaughtException1, "WindowPresentationStore.Load")
                Return Nothing
            End Try

            Return Nothing
        End Function

        Friend Shared Function Save(key As String,
                                    state As MASWindowPresentationState) As Boolean
            If state Is Nothing Then Return False

            Try
                Dim path As String = ResolvePath(key)
                If String.IsNullOrWhiteSpace(path) Then Return False

                Dim folder As String = System.IO.Path.GetDirectoryName(path)
                If Not String.IsNullOrWhiteSpace(folder) AndAlso Not Directory.Exists(folder) Then
                    Directory.CreateDirectory(folder)
                End If

                Dim builder As New StringBuilder()
                builder.AppendLine("Version=1")
                builder.AppendLine("ProfileKind=" & state.ProfileKind.ToString())
                builder.AppendLine("WindowState=" & state.WindowState.ToString())
                builder.AppendLine("Bounds=" & FormatBounds(state.Bounds))

                Dim tempPath As String = path & ".tmp"
                File.WriteAllText(tempPath, builder.ToString(), Encoding.UTF8)

                If File.Exists(path) Then File.Delete(path)
                File.Move(tempPath, path)
                Return True
            Catch masCaughtException2 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowFileSystemBoundary(masCaughtException2, "WindowPresentationStore.Save")
                Return False
            End Try
        End Function

        Private Shared Function ResolvePath(key As String) As String
            Dim safeKey As String = MASRuntimeSettingsPathResolver.SanitizePathSegment(key, String.Empty)
            If String.IsNullOrWhiteSpace(safeKey) Then Return String.Empty
            Return MASRuntimeSettingsPathResolver.ResolveApplicationSettingsFilePath(safeKey & FileExtension, FolderName)
        End Function

        Private Shared Function ParseBounds(value As String) As Rectangle
            If String.IsNullOrWhiteSpace(value) Then Return Rectangle.Empty

            Dim parts As String() = value.Split(","c)
            If parts Is Nothing OrElse parts.Length <> 4 Then Return Rectangle.Empty

            Dim x As Integer
            Dim y As Integer
            Dim width As Integer
            Dim height As Integer

            If Not Integer.TryParse(parts(0).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, x) Then Return Rectangle.Empty
            If Not Integer.TryParse(parts(1).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, y) Then Return Rectangle.Empty
            If Not Integer.TryParse(parts(2).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, width) Then Return Rectangle.Empty
            If Not Integer.TryParse(parts(3).Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, height) Then Return Rectangle.Empty

            If width <= 0 OrElse height <= 0 Then Return Rectangle.Empty
            Return New Rectangle(x, y, width, height)
        End Function

        Private Shared Function FormatBounds(bounds As Rectangle) As String
            Return bounds.X.ToString(CultureInfo.InvariantCulture) & "," &
                   bounds.Y.ToString(CultureInfo.InvariantCulture) & "," &
                   bounds.Width.ToString(CultureInfo.InvariantCulture) & "," &
                   bounds.Height.ToString(CultureInfo.InvariantCulture)
        End Function

    End Class

End Namespace
