Option Strict On
Option Explicit On

Imports System
Imports System.Globalization
Imports Nexamas.UI.Theming
Imports Nexamas.UI.Values
Imports SkiaSharp

Namespace Nexamas.UI.Components

    ''' <summary>
    ''' Friend-owned policy for MASAgendaView. It centralizes text hygiene, date and
    ''' hour normalization, visible-event windows, RTL detection, theme color resolution,
    ''' and explicit architecture boundary facts for agenda ownership.
    ''' </summary>
    Friend NotInheritable Class MASAgendaViewPolicy
        Private Sub New()
        End Sub

        Friend Shared Function NormalizeTitle(value As String) As String
            Return NormalizeText(value, AgendaViewTokens.DefaultTitle, 96)
        End Function

        Friend Shared Function NormalizeEventTitle(value As String) As String
            Return NormalizeText(value, AgendaViewTokens.DefaultEventTitle, 96)
        End Function

        Friend Shared Function NormalizeEventDetail(value As String) As String
            Return NormalizeText(value, String.Empty, 140)
        End Function

        Friend Shared Function NormalizeKey(value As String,
                                            fallbackPrefix As String,
                                            fallbackIndex As Integer) As String
            Dim normalized As String = If(value, String.Empty).Trim()
            If normalized.Length = 0 Then normalized = fallbackPrefix & Math.Max(1, fallbackIndex).ToString(CultureInfo.InvariantCulture)
            If normalized.Length > 64 Then normalized = normalized.Substring(0, 64)
            Return normalized
        End Function

        Friend Shared Function NormalizeText(value As String,
                                             fallback As String,
                                             maxLength As Integer) As String
            Dim normalized As String = If(value, String.Empty).Trim()
            If normalized.Length = 0 Then normalized = If(fallback, String.Empty)
            normalized = normalized.Replace(ControlChars.Cr, " "c).Replace(ControlChars.Lf, " "c).Replace(ControlChars.Tab, " "c)
            While normalized.Contains("  ")
                normalized = normalized.Replace("  ", " ")
            End While
            If maxLength > 0 AndAlso normalized.Length > maxLength Then normalized = normalized.Substring(0, maxLength)
            Return normalized
        End Function

        Friend Shared Function NormalizeDay(value As Date) As Date
            Return value.Date
        End Function

        Friend Shared Function NormalizeEventDay(startTime As DateTime,
                                                 fallbackDay As Date) As Date
            Dim normalized As Date = startTime.Date
            If normalized = DateTime.MinValue.Date Then Return NormalizeDay(fallbackDay)
            Return normalized
        End Function

        Friend Shared Function NormalizeViewMode(value As MASAgendaViewMode) As MASAgendaViewMode
            Select Case value
                Case MASAgendaViewMode.Week, MASAgendaViewMode.Month
                    Return value
                Case Else
                    Return MASAgendaViewMode.Day
            End Select
        End Function

        Friend Shared Function NormalizeHour(value As Integer) As Integer
            If value < 0 Then Return 0
            If value > 23 Then Return 23
            Return value
        End Function

        Friend Shared Sub NormalizeHourRange(ByRef startHour As Integer,
                                             ByRef endHour As Integer)
            startHour = NormalizeHour(startHour)
            endHour = NormalizeHour(endHour)
            If endHour <= startHour Then
                If startHour >= 23 Then
                    startHour = 22
                    endHour = 23
                Else
                    endHour = Math.Min(23, startHour + 1)
                End If
            End If
        End Sub

        Friend Shared Function MinutesOfDay(value As DateTime) As Integer
            Return Math.Max(0, Math.Min(1439, value.Hour * 60 + value.Minute))
        End Function

        Friend Shared Function ClampMinuteToRange(value As Integer,
                                                  startHour As Integer,
                                                  endHour As Integer) As Integer
            Dim minMinute As Integer = NormalizeHour(startHour) * 60
            Dim maxMinute As Integer = Math.Min(1439, NormalizeHour(endHour) * 60)
            If value < minMinute Then Return minMinute
            If value > maxMinute Then Return maxMinute
            Return value
        End Function

        Friend Shared Function BuildDayTitle(day As Date) As String
            Return NormalizeDay(day).ToString("dddd, d MMMM yyyy", CultureInfo.CurrentCulture)
        End Function

        Friend Shared Function BuildViewTitle(day As Date,
                                              mode As MASAgendaViewMode) As String
            Select Case NormalizeViewMode(mode)
                Case MASAgendaViewMode.Week
                    Dim startDay As Date = ResolveWeekStart(day)
                    Dim endDay As Date = startDay.AddDays(6)
                    Return startDay.ToString("d MMM", CultureInfo.CurrentCulture) & " – " & endDay.ToString("d MMM yyyy", CultureInfo.CurrentCulture)
                Case MASAgendaViewMode.Month
                    Return NormalizeDay(day).ToString("MMMM yyyy", CultureInfo.CurrentCulture)
                Case Else
                    Return BuildDayTitle(day)
            End Select
        End Function

        Friend Shared Function BuildTimeText(startMinute As Integer,
                                             endMinute As Integer) As String
            Dim baseDate As Date = Date.Today
            Dim startValue As DateTime = baseDate.AddMinutes(Math.Max(0, Math.Min(1439, startMinute)))
            Dim endValue As DateTime = baseDate.AddMinutes(Math.Max(0, Math.Min(1439, endMinute)))
            Return startValue.ToString("t", CultureInfo.CurrentCulture) & "–" & endValue.ToString("t", CultureInfo.CurrentCulture)
        End Function

        Friend Shared Function BuildSummary(eventCount As Integer,
                                            day As Date,
                                            mode As MASAgendaViewMode) As String
            Dim countText As String = If(eventCount = 1, "1 event", eventCount.ToString(CultureInfo.CurrentCulture) & " events")
            Return countText & " • " & BuildViewTitle(day, mode)
        End Function

        Friend Shared Function ResolveWeekStart(day As Date) As Date
            Dim normalized As Date = NormalizeDay(day)
            Dim first As DayOfWeek = CultureInfo.CurrentCulture.DateTimeFormat.FirstDayOfWeek
            Dim delta As Integer = (7 + CInt(normalized.DayOfWeek) - CInt(first)) Mod 7
            Return normalized.AddDays(-delta)
        End Function

        Friend Shared Function ResolveRangeStart(day As Date,
                                                 mode As MASAgendaViewMode) As Date
            Dim normalized As Date = NormalizeDay(day)
            Select Case NormalizeViewMode(mode)
                Case MASAgendaViewMode.Week
                    Return ResolveWeekStart(normalized)
                Case MASAgendaViewMode.Month
                    Return New Date(normalized.Year, normalized.Month, 1)
                Case Else
                    Return normalized
            End Select
        End Function

        Friend Shared Function ResolveRangeEndInclusive(day As Date,
                                                        mode As MASAgendaViewMode) As Date
            Dim normalized As Date = NormalizeDay(day)
            Select Case NormalizeViewMode(mode)
                Case MASAgendaViewMode.Week
                    Return ResolveWeekStart(normalized).AddDays(6)
                Case MASAgendaViewMode.Month
                    Return New Date(normalized.Year, normalized.Month, DateTime.DaysInMonth(normalized.Year, normalized.Month))
                Case Else
                    Return normalized
            End Select
        End Function

        Friend Shared Function ResolveMonthGridStart(day As Date) As Date
            Return ResolveWeekStart(New Date(NormalizeDay(day).Year, NormalizeDay(day).Month, 1))
        End Function

        Friend Shared Function ResolveRangeCellCount(mode As MASAgendaViewMode) As Integer
            Select Case NormalizeViewMode(mode)
                Case MASAgendaViewMode.Week
                    Return 7
                Case MASAgendaViewMode.Month
                    Return 42
                Case Else
                    Return 1
            End Select
        End Function

        Friend Shared Function MoveRange(day As Date,
                                         mode As MASAgendaViewMode,
                                         delta As Integer) As Date
            Dim normalized As Date = NormalizeDay(day)
            Select Case NormalizeViewMode(mode)
                Case MASAgendaViewMode.Week
                    Return normalized.AddDays(7 * Math.Sign(delta))
                Case MASAgendaViewMode.Month
                    Return normalized.AddMonths(Math.Sign(delta))
                Case Else
                    Return normalized.AddDays(Math.Sign(delta))
            End Select
        End Function

        Friend Shared Function ClampIndex(index As Integer,
                                          count As Integer) As Integer
            If count <= 0 Then Return -1
            If index < 0 Then Return 0
            If index >= count Then Return count - 1
            Return index
        End Function

        Friend Shared Function EnsureVisibleEventIndex(selectedIndex As Integer,
                                                       currentTopIndex As Integer,
                                                       eventCount As Integer) As Integer
            If eventCount <= 0 Then Return 0
            Dim maxTop As Integer = Math.Max(0, eventCount - AgendaViewTokens.MaxVisibleEvents)
            Dim top As Integer = Math.Max(0, Math.Min(currentTopIndex, maxTop))
            If selectedIndex < 0 Then Return top
            If selectedIndex < top Then Return Math.Max(0, selectedIndex)
            If selectedIndex >= top + AgendaViewTokens.MaxVisibleEvents Then
                Return Math.Max(0, Math.Min(maxTop, selectedIndex - AgendaViewTokens.MaxVisibleEvents + 1))
            End If
            Return top
        End Function


        Friend Shared Function EnsureVisibleEventPosition(selectedPosition As Integer,
                                                          currentTopPosition As Integer,
                                                          visibleEventCount As Integer,
                                                          visibleCapacity As Integer) As Integer
            If visibleEventCount <= 0 Then Return 0
            Dim capacity As Integer = Math.Max(1, visibleCapacity)
            Dim maxTop As Integer = Math.Max(0, visibleEventCount - capacity)
            Dim top As Integer = Math.Max(0, Math.Min(currentTopPosition, maxTop))
            If selectedPosition < 0 Then Return top
            If selectedPosition < top Then Return Math.Max(0, selectedPosition)
            If selectedPosition >= top + capacity Then
                Return Math.Max(0, Math.Min(maxTop, selectedPosition - capacity + 1))
            End If
            Return top
        End Function

        Friend Shared Function ResolveRightToLeft() As Boolean
            Try
                Return Nexamas.UI.Localization.MASLocalization.IsCurrentRightToLeft()
            Catch ex As Exception
                Nexamas.UI.Diagnostics.MASExceptionSilencer.SwallowInputBoundary(ex, "MASAgendaViewPolicy.ResolveRightToLeft")
                Return False
            End Try
        End Function

        Friend Shared Function ResolveAccentColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.BrandTheme IsNot Nothing Then Return ctx.BrandTheme.BrandPrimary
            If ctx IsNot Nothing AndAlso ctx.SemanticTheme IsNot Nothing Then Return ctx.SemanticTheme.Info
            Return New SKColor(64, 132, 246)
        End Function

        Friend Shared Function ResolvePrimaryTextColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then Return ctx.TextColorTheme.PrimaryText.WithAlpha(AgendaViewTokens.TextAlpha)
            Return Nexamas.UI.Values.Color.Text.Primary.WithAlpha(AgendaViewTokens.TextAlpha)
        End Function

        Friend Shared Function ResolveMutedTextColor(ctx As MASThemeContext) As SKColor
            If ctx IsNot Nothing AndAlso ctx.TextColorTheme IsNot Nothing Then Return ctx.TextColorTheme.SecondaryText.WithAlpha(AgendaViewTokens.MutedTextAlpha)
            Return Nexamas.UI.Values.Color.Text.Secondary.WithAlpha(AgendaViewTokens.MutedTextAlpha)
        End Function

        Friend Shared Function HasNoRecurrenceEnginePath() As Boolean
            Return True
        End Function

        Friend Shared Function HasNoReminderTransportPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasNoExternalCalendarProviderPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasNoBookingStoragePath() As Boolean
            Return True
        End Function

        Friend Shared Function HasNoSchedulerEnginePath() As Boolean
            Return True
        End Function


        Friend Shared Function HasOverlapLayoutPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasDeterministicNowProviderPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasSingleDayTimeWindowPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasEventDayOwnershipPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasWeekMonthRangeViewPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasAgendaSourceProjectionPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasVisibleRangeWindowingProofPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasRecurrenceTimeZonePolicyPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasEventMoveResizeContractPath() As Boolean
            Return True
        End Function

        Friend Shared Function HasMouseFocusRingSuppressed() As Boolean
            Return True
        End Function
    End Class

End Namespace
