Option Strict On
Option Explicit On


Imports System.Runtime.InteropServices
Imports System.Windows.Forms

Namespace Nexamas.UI.Components

    '========================================================
    ' MASDwmShadownew (UNIFIED)
    '--------------------------------------------------------
    ' - Enables window shadows using DWM or classic CS_DROPSHADOW based on mode.
    ' - Provides PopupSafe mode to avoid Win11 black-corner flashes (NO ExtendFrame).
    ' - Keeps back-compat knobs (ApplyDelayMs / UsePulseFix / Mode / ShadowModeValue).
    '========================================================
    Friend NotInheritable Class MASDwmShadow
        Private Sub New()
        End Sub

        Friend Enum ShadowMode
            SystemDwm = 0   ' Main windows (DWM + ExtendFrame)
            Classic = 1     ' CS_DROPSHADOW only
            PopupSafe = 2   ' Classic + Rounded corners, NO ExtendFrame
        End Enum

        ' Old knobs (kept)
        Friend Shared Property ApplyDelayMs As Integer = 0
        Friend Shared Property UsePulseFix As Boolean = False
        Friend Shared Property Mode As ShadowMode = ShadowMode.SystemDwm

        ' Back-compat alias property name
        Friend Shared Property ShadowModeValue As ShadowMode
            Get
                Return Mode
            End Get
            Set(value As ShadowMode)
                Mode = value
            End Set
        End Property

        '========================================================
        ' Public API
        '========================================================
        Friend Shared Sub Enable(form As Form)
            If form Is Nothing OrElse form.IsDisposed Then Return
            If Not form.IsHandleCreated Then Return

            If ApplyDelayMs > 0 Then
                Dim t As New Timer() With {.Interval = Nexamas.UI.Timing.MASVisualClock.NormalizeVisualPulseIntervalMs(ApplyDelayMs)}
                AddHandler t.Tick,
                    Sub()
                        t.Stop()
                        t.Dispose()

                        If form Is Nothing OrElse form.IsDisposed Then Return
                        If Not form.IsHandleCreated Then Return

                        Enable(form.Handle, Mode)
                    End Sub
                t.Start()
            Else
                Enable(form.Handle, Mode)
            End If
        End Sub

        ' Back-compat overload: Enable(form, delayMs, usePulseFix)
        Friend Shared Sub Enable(form As Form, delayMs As Integer, enablePulseFix As Boolean)
            ApplyDelayMs = Math.Max(0, delayMs)
            UsePulseFix = enablePulseFix ' ✅ FIXED
            Enable(form)
        End Sub

        Friend Shared Sub Enable(hwnd As IntPtr)
            Enable(hwnd, Mode)
        End Sub

        ' Popup-safe helpers
        Friend Shared Sub EnablePopup(form As Form)
            If form Is Nothing OrElse form.IsDisposed Then Return
            If Not form.IsHandleCreated Then Return
            Enable(form.Handle, ShadowMode.PopupSafe)
        End Sub

        Friend Shared Sub EnablePopup(hwnd As IntPtr)
            If hwnd = IntPtr.Zero Then Return
            Enable(hwnd, ShadowMode.PopupSafe)
        End Sub

        '========================================================
        ' Core
        '========================================================
        Friend Shared Sub Enable(hwnd As IntPtr, mode As ShadowMode)
            If hwnd = IntPtr.Zero Then Return

            Select Case mode
                Case ShadowMode.Classic
                    EnableClassicClassShadow(hwnd)
                    Return

                Case ShadowMode.PopupSafe
                    ' ✅ Stable shadow, avoids black-corner flash: NO ExtendFrame
                    EnableClassicClassShadow(hwnd)
                    ApplySystemRoundedCorners(hwnd)
                    Return

                Case Else
                    ' SystemDwm (main windows)
                    If Not IsDwmCompositionEnabled() Then
                        EnableClassicClassShadow(hwnd)
                        Return
                    End If

                    Dim policy As Integer = DWMNCRP_ENABLED
                    DwmSetWindowAttribute(hwnd, DWMWA_NCRENDERING_POLICY, policy, Marshal.SizeOf(GetType(Integer)))

                    ' DWM shadow trigger (OK for main windows)
                    Dim m As New MARGINS(1, 1, 1, 1)
                    DwmExtendFrameIntoClientArea(hwnd, m)

                    If UsePulseFix Then
                        PulseNCArea(hwnd)
                    End If

                    ' Best-effort toggles (ignored on some builds)
                    Dim onVal As Integer = 1
                    TrySetAttr(hwnd, 1029, onVal)
                    TrySetAttr(hwnd, 1030, onVal)

                    ' Also apply classic class shadow as fallback
                    EnableClassicClassShadow(hwnd)
            End Select
        End Sub

        '========================================================
        ' Win11 rounded corners (anti-aliased)
        '========================================================
        Friend Shared Sub ApplySystemRoundedCorners(form As Form)
            If form Is Nothing OrElse form.IsDisposed Then Return
            If Not form.IsHandleCreated Then Return
            ApplySystemRoundedCorners(form.Handle)
        End Sub

        Friend Shared Sub ApplySystemRoundedCorners(hwnd As IntPtr)
            If hwnd = IntPtr.Zero Then Return
            If Not IsDwmCompositionEnabled() Then Return

            Const DWMWA_WINDOW_CORNER_PREFERENCE As Integer = 33
            Const DWMWCP_ROUND As Integer = 2

            Try
                Dim v As Integer = DWMWCP_ROUND
                DwmSetWindowAttribute(hwnd, DWMWA_WINDOW_CORNER_PREFERENCE, v, Marshal.SizeOf(GetType(Integer)))
            Catch masCaughtException1 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException1)
            End Try
        End Sub

        '========================================================
        ' Internals
        '========================================================
        Private Shared Function IsDwmCompositionEnabled() As Boolean
            Try
                Dim enabled As Boolean = False
                Dim hr As Integer = DwmIsCompositionEnabled(enabled)
                Return (hr = 0 AndAlso enabled)
            Catch masCaughtException2 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException2)
                Return False
            End Try
        End Function

        Private Shared Sub TrySetAttr(hwnd As IntPtr, attr As Integer, value As Integer)
            Try
                DwmSetWindowAttribute(hwnd, attr, value, Marshal.SizeOf(GetType(Integer)))
            Catch masCaughtException3 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException3)
            End Try
        End Sub

        Private Shared Sub EnableClassicClassShadow(hwnd As IntPtr)
            Const CS_DROPSHADOW As Integer = &H20000
            Const GCL_STYLE As Integer = -26

            Try
                Dim style As Long = GetClassLongPtr(hwnd, GCL_STYLE).ToInt64()
                If (style And CS_DROPSHADOW) = 0 Then
                    SetClassLongPtr(hwnd, GCL_STYLE, New IntPtr(style Or CS_DROPSHADOW))
                End If
            Catch masCaughtException4 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException4)
            End Try
        End Sub

        Private Shared Sub PulseNCArea(hwnd As IntPtr)
            Try
                Const SWP_NOSIZE As UInteger = &H1UI
                Const SWP_NOMOVE As UInteger = &H2UI
                Const SWP_NOZORDER As UInteger = &H4UI
                Const SWP_NOACTIVATE As UInteger = &H10UI
                Const SWP_FRAMECHANGED As UInteger = &H20UI
                SetWindowPos(hwnd, IntPtr.Zero, 0, 0, 0, 0,
                             SWP_NOMOVE Or SWP_NOSIZE Or SWP_NOZORDER Or SWP_NOACTIVATE Or SWP_FRAMECHANGED)
            Catch masCaughtException5 As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowRenderFallback(masCaughtException5)
            End Try
        End Sub

#Region "WinAPI"

        Private Const DWMWA_NCRENDERING_POLICY As Integer = 2
        Private Const DWMNCRP_ENABLED As Integer = 2

        <StructLayout(LayoutKind.Sequential)>
        Private Structure MARGINS
            Friend cxLeftWidth As Integer
            Friend cxRightWidth As Integer
            Friend cyTopHeight As Integer
            Friend cyBottomHeight As Integer

            Friend Sub New(l As Integer, r As Integer, t As Integer, b As Integer)
                cxLeftWidth = l
                cxRightWidth = r
                cyTopHeight = t
                cyBottomHeight = b
            End Sub
        End Structure

        <DllImport("dwmapi.dll")>
        Private Shared Function DwmIsCompositionEnabled(ByRef pfEnabled As Boolean) As Integer
        End Function

        <DllImport("dwmapi.dll")>
        Private Shared Function DwmSetWindowAttribute(hWnd As IntPtr, dwAttribute As Integer, ByRef pvAttribute As Integer, cbAttribute As Integer) As Integer
        End Function

        <DllImport("dwmapi.dll")>
        Private Shared Function DwmExtendFrameIntoClientArea(hWnd As IntPtr, ByRef pMarInset As MARGINS) As Integer
        End Function

        <DllImport("user32.dll")>
        Private Shared Function SetWindowPos(hWnd As IntPtr, hWndInsertAfter As IntPtr, X As Integer, Y As Integer, cx As Integer, cy As Integer, uFlags As UInteger) As Boolean
        End Function

        <DllImport("user32.dll", EntryPoint:="GetClassLong")>
        Private Shared Function GetClassLong32(hWnd As IntPtr, nIndex As Integer) As Integer
        End Function

        <DllImport("user32.dll", EntryPoint:="GetClassLongPtr")>
        Private Shared Function GetClassLongPtr64(hWnd As IntPtr, nIndex As Integer) As IntPtr
        End Function

        <DllImport("user32.dll", EntryPoint:="SetClassLong")>
        Private Shared Function SetClassLong32(hWnd As IntPtr, nIndex As Integer, dwNewLong As Integer) As Integer
        End Function

        <DllImport("user32.dll", EntryPoint:="SetClassLongPtr")>
        Private Shared Function SetClassLongPtr64(hWnd As IntPtr, nIndex As Integer, dwNewLong As IntPtr) As IntPtr
        End Function

        Private Shared Function GetClassLongPtr(hWnd As IntPtr, nIndex As Integer) As IntPtr
            If IntPtr.Size = 8 Then
                Return GetClassLongPtr64(hWnd, nIndex)
            Else
                Return New IntPtr(GetClassLong32(hWnd, nIndex))
            End If
        End Function

        Private Shared Sub SetClassLongPtr(hWnd As IntPtr, nIndex As Integer, dwNewLong As IntPtr)
            If IntPtr.Size = 8 Then
                SetClassLongPtr64(hWnd, nIndex, dwNewLong)
            Else
                SetClassLong32(hWnd, nIndex, dwNewLong.ToInt32())
            End If
        End Sub

#End Region

    End Class

End Namespace
