<%
'=======================================================================================================================
' ROUTING HELPER
' Provides URL generation for RouteKit framework
'=======================================================================================================================
Class Route_Helper_Class
    Private m_app_url
    Private m_content_url
    Private m_stylesheets_url
    Private m_js_url
    Private m_images_url
    Private m_enable_cache_busting
    Private m_cache_bust_param_name

    Private Sub Class_Initialize()
        ' Auto-detect application URL from current request
        Dim protocol, host, appPath
        protocol = IIf(Request.ServerVariables("HTTPS") = "on", "https://", "http://")
        host = Request.ServerVariables("HTTP_HOST")
        appPath = Request.ServerVariables("APPL_MD_PATH")

        ' Extract virtual directory from IIS path
        Dim vdir
        vdir = ""
        If InStr(appPath, "/LM/W3SVC/") > 0 Then
            vdir = Mid(appPath, InStrRev(appPath, "/") + 1)
            If vdir <> "ROOT" Then
                vdir = "/" & vdir
            Else
                vdir = ""
            End If
        End If

        m_app_url = protocol & host & vdir & "/"
        m_content_url = m_app_url & "content/"
        m_stylesheets_url = m_app_url & "css/"
        m_js_url = m_app_url & "js/"
        m_images_url = m_app_url & "images/"

        ' Load cache-busting configuration
        Dim cacheBustSetting
        cacheBustSetting = GetAppSetting("EnableCacheBusting")
        m_enable_cache_busting = (cacheBustSetting = "true" Or cacheBustSetting = "True")

        ' Get cache-bust parameter name (default: "v")
        m_cache_bust_param_name = GetAppSetting("CacheBustParamName")
        If m_cache_bust_param_name = "nothing" Or Len(m_cache_bust_param_name) = 0 Then
            m_cache_bust_param_name = "v"
        End If
    End Sub

    '---------------------------------------------------------------------------------------------------------------------
    ' Cache-busting token (timestamp-based for uniqueness)
    '---------------------------------------------------------------------------------------------------------------------
    Public Property Get NoCacheToken
        NoCacheToken = CLng(Timer() * 100)
    End Property

    '---------------------------------------------------------------------------------------------------------------------
    ' Check if cache-busting is globally enabled
    '---------------------------------------------------------------------------------------------------------------------
    Public Property Get CacheBustingEnabled
        CacheBustingEnabled = m_enable_cache_busting
    End Property

    '---------------------------------------------------------------------------------------------------------------------
    ' Get/Set cache-busting enabled (can override config at runtime)
    '---------------------------------------------------------------------------------------------------------------------
    Public Property Let CacheBustingEnabled(value)
        m_enable_cache_busting = value
    End Property

    '---------------------------------------------------------------------------------------------------------------------
    ' URL Properties
    '---------------------------------------------------------------------------------------------------------------------
    Public Property Get AppURL
        AppURL = m_app_url
    End Property

    Public Property Get ContentURL
        ContentURL = m_content_url
    End Property

    Public Property Get StylesheetsURL
        StylesheetsURL = m_stylesheets_url
    End Property

    Public Property Get JsURL
        JsURL = m_js_url
    End Property

    Public Property Get ImagesURL
        ImagesURL = m_images_url
    End Property

    '---------------------------------------------------------------------------------------------------------------------
    ' Generate clean URL for controller/action (RouteKit style)
    '
    ' @param controller_name   String      Name of controller (without "Controller" suffix)
    ' @param action_name       String      Name of action method
    ' @param params_array      KV Array    Optional key/value pair array for query string
    ' @returns                 String      Clean URL like "/controller/action?key=val"
    '---------------------------------------------------------------------------------------------------------------------
    Public Function UrlTo(controller_name, action_name, params_array)
        Dim url, qs

        ' Build clean URL: /controller/action
        url = m_app_url & LCase(controller_name) & "/" & LCase(action_name)

        ' Add query string parameters if provided
        qs = TO_Querystring(params_array)
        If Len(qs) > 0 Then
            url = url & "?" & qs
        End If

        UrlTo = url
    End Function

    '---------------------------------------------------------------------------------------------------------------------
    ' Generate URL with route parameters (e.g., /users/show/123)
    '
    ' @param controller_name   String      Name of controller
    ' @param action_name       String      Name of action method
    ' @param route_params      Array       Route parameters (e.g., Array(123) for ID)
    ' @param query_params      KV Array    Optional query string parameters
    ' @returns                 String      URL with route params
    '---------------------------------------------------------------------------------------------------------------------
    Public Function UrlToWithParams(controller_name, action_name, route_params, query_params)
        Dim url, qs, i

        ' Build base URL
        url = m_app_url & LCase(controller_name) & "/" & LCase(action_name)

        ' Append route parameters
        If IsArray(route_params) Then
            For i = 0 To UBound(route_params)
                url = url & "/" & Server.URLEncode(CStr(route_params(i)))
            Next
        ElseIf Not IsEmpty(route_params) Then
            url = url & "/" & Server.URLEncode(CStr(route_params))
        End If

        ' Add query string parameters if provided
        qs = TO_Querystring(query_params)
        If Len(qs) > 0 Then
            url = url & "?" & qs
        End If

        UrlToWithParams = url
    End Function

    '---------------------------------------------------------------------------------------------------------------------
    ' Generate URL for static asset with cache-busting
    '
    ' @param asset_path        String      Relative path to asset (e.g., "css/site.css")
    ' @param use_cache_bust    Variant     Boolean or Empty. If Empty, uses global setting. If True/False, overrides.
    ' @returns                 String      Full URL to asset
    '---------------------------------------------------------------------------------------------------------------------
    Public Function AssetUrl(asset_path, use_cache_bust)
        Dim url, shouldBust
        url = m_app_url & asset_path

        ' Determine if we should cache-bust
        If IsEmpty(use_cache_bust) Then
            shouldBust = m_enable_cache_busting
        Else
            shouldBust = CBool(use_cache_bust)
        End If

        If shouldBust Then
            url = AppendCacheBustParam(url)
        End If

        AssetUrl = url
    End Function

    '---------------------------------------------------------------------------------------------------------------------
    ' Generate URL for route with optional cache-busting
    '
    ' @param controller_name   String      Name of controller
    ' @param action_name       String      Name of action
    ' @param params_array      KV Array    Optional query params
    ' @param use_cache_bust    Variant     Boolean or Empty. If Empty, uses global setting
    ' @returns                 String      URL with optional cache-busting
    '---------------------------------------------------------------------------------------------------------------------
    Public Function UrlToWithCacheBust(controller_name, action_name, params_array, use_cache_bust)
        Dim url
        url = UrlTo(controller_name, action_name, params_array)

        ' Determine if we should cache-bust
        Dim shouldBust
        If IsEmpty(use_cache_bust) Then
            shouldBust = m_enable_cache_busting
        Else
            shouldBust = CBool(use_cache_bust)
        End If

        If shouldBust Then
            url = AppendCacheBustParam(url)
        End If

        UrlToWithCacheBust = url
    End Function


    '---------------------------------------------------------------------------------------------------------------------
    ' PRIVATE HELPER METHODS
    '---------------------------------------------------------------------------------------------------------------------
    Private Function TO_Querystring(the_array)
        Dim result, idx
        result = ""

        If Not IsEmpty(the_array) And IsArray(the_array) Then
            ' Process key-value pairs (array with even number of elements)
            For idx = LBound(the_array) To UBound(the_array) Step 2
                If idx + 1 <= UBound(the_array) Then
                    result = result & GetParam(the_array, idx)
                    ' Append & between parameters, but not on the last parameter
                    If Not (idx >= UBound(the_array) - 1) Then
                        result = result & "&"
                    End If
                End If
            Next
        End If

        TO_Querystring = result
    End Function

    Private Function GetParam(params_array, key_idx)
        Dim key, val
        key = Server.URLEncode(CStr(params_array(key_idx)))
        val = Server.URLEncode(CStr(params_array(key_idx + 1)))
        GetParam = key & "=" & val
    End Function

    Private Function AppendCacheBustParam(url)
        Dim separator
        ' Determine if we need ? or &
        If InStr(url, "?") > 0 Then
            separator = "&"
        Else
            separator = "?"
        End If
        AppendCacheBustParam = url & separator & m_cache_bust_param_name & "=" & NoCacheToken
    End Function
End Class


'---------------------------------------------------------------------------------------------------------------------
' Singleton accessor
'---------------------------------------------------------------------------------------------------------------------
Dim Route_Helper__Singleton
Set Route_Helper__Singleton = Nothing

Function Routes()
    If Route_Helper__Singleton Is Nothing Then
        Set Route_Helper__Singleton = New Route_Helper_Class
    End If
    Set Routes = Route_Helper__Singleton
End Function

%>
