set _get_vars = (
    SELECT
        json_group_object(
            "key",
            iif(CAST(CAST(value AS NUMERIC) AS TEXT) = value, CAST(value AS NUMERIC), value)
        ) AS get_var
    FROM
        json_each(sqlpage.variables('GET'))
    WHERE NOT "key" like '\_%' ESCAPE '\'
);


set _locale_code = $lang;                         -- 'en', 'ru', 'de', 'fr', 'zh-cn'
set _theme = 'fancy'; --$theme;                              -- 'default', 'fancy'
set _hide_language_names = $hide_language_names;  -- 0, 1 (BOOLEAN)
set _authenticated = $authenticated;              -- 0, 1 (BOOLEAN)

-- =============================================================================
-- =============================================================================

WITH

--  test_values(_locale_code,  _theme,   _hide_language_names, _authenticated ) AS (VALUES
--             (    'en',      'fancy',          TRUE,               FALSE)
--             (    NULL,        NULL,           NULL,               NULL)
--             (    'fr',      'default',        TRUE,               TRUE)
--  ),
     
    -- Replaces values with appropriate variables
    -- ifnull guuards from invalid JSON errors

    config_user AS (
        SELECT
            lower(ifnull($_locale_code, '_'))               AS locale_code,
            lower(ifnull($_theme, '_'))                     AS theme,
            CAST($_hide_language_names AS INTEGER)          AS hide_language_names,
            CAST(ifnull($_authenticated, FALSE) AS INTEGER) AS authenticated
--      FROM test_values
    ),
    
    -- Inputs data guards
    
    config_guards AS (
        SELECT
            (
                SELECT iif(contents  ->> ('$.' || locale_code) IS NULL, NULL, locale_code)
                FROM sqlpage_files
                WHERE path = 'locales/locales.json'
            ) AS locale_code,
            (
                SELECT iif(contents  ->> ('$.' || theme) IS NULL, NULL, theme)
                FROM sqlpage_files
                WHERE path = 'themes/themes.json'
            ) AS theme,
            hide_language_names,
            authenticated
        FROM config_user
    ),
    
    -- Retrieves locale and theme JSON data
    
    config AS (
        SELECT
            iif(locale_code IS NULL, NULL, (
                SELECT contents ->> '$.menu'
                FROM sqlpage_files
                WHERE path = 'locales/' || locale_code || '/locale.json'
            )) AS locale,
            iif(theme IS NULL, NULL, (
                SELECT contents ->> '$.menu'
                FROM sqlpage_files
                WHERE path = 'themes/' || theme || '/theme.json'
            )) AS theme,
            (
                SELECT contents ->> '$.menu'
                FROM sqlpage_files
                WHERE path = 'themes/default/theme.json'
            ) AS theme_default,
            (
                SELECT contents ->> '$.meta.label'
                FROM sqlpage_files
                WHERE path = 'locales/' || locale_code || '/locale.json'
            ) AS locale_label,
            hide_language_names,
            authenticated
        FROM config_guards
    ),
    
    -- Prepares language items.
    -- This is a dynamically generated menu item.
    
    locale_codes AS (
        SELECT "key" AS code, value AS position
        FROM sqlpage_files, json_each(contents)
        WHERE sqlpage_files.path = 'locales/locales.json'
    ),
    languages AS (
        SELECT
            position,
            code,
            contents ->> '$.meta.label' AS label
        FROM sqlpage_files, locale_codes 
        WHERE path like 'locales/%/locale.json'
          AND contents ->> '$.meta.code' = code COLLATE NOCASE
        ORDER BY position
    ),
    
    -- Prepares a list of top menu items with default icons.
    -- The language menu includes the "global/neutral/undefinded" icon.
    
    top_menus_global AS (
        SELECT
            position,
            label,

            -- Hide top menu with submenu if a particular filter is included in
            -- state_filter and its current value does match the specified value.
            --
            -- Note that the "class" attribute is set to two classes:
            -- 'menu_' || lower(label) and the same with '_slim' suffix.
            -- These classes are applied to respective submenus for css-based fine-tuning.
            
            CASE
                WHEN (state_filter ->> '$.authenticated') IS NULL
                  OR state_filter ->> '$.authenticated' = ifnull(authenticated, FALSE) THEN
                    json_object(
                        'title', iif(icon_only IS TRUE, NULL, ifnull(locale ->> ('$.' || label), label)),
                        iif(theme IS NULL, 'icon', 'image'),
                        iif(theme IS NULL, tabler_icon, '/' || (theme ->> ('$.' || label))),
                        'class',
                                 -- Handles special cases: only sets the '_slim' class on the 'Language'
                                 -- menu when language names (labels) are hidden. Only set the base class
								 -- for English localization (the extra whitespaces are painfull...)
                                 iif(ifnull(locale_label, 'English') IN ('English', 'Chinese'),
								     ' menu_' || lower(label), '') ||
                                 iif(label = 'Language' AND hide_language_names IS NOT TRUE, '',
                                     ' menu_' || lower(label) || '_slim'
                                 )
                    )
                ELSE
                    NULL
            END AS top_item
        FROM menus, config
        WHERE parent_label IS NULL
        ORDER BY position
    ),

    -- The sole purpose of this separate modification is to set the icon
    -- of the top language menu to reflect the current locale

    top_menus AS (
        SELECT
            position,
            label,
            iif(label <> 'Language' OR locale IS NULL OR top_item IS NULL,
                top_item,
                json_set(
                    top_item,
                    '$.image',
                    '/' || (theme ->> ('$.' || locale_label))
                )
             ) AS top_item
        FROM top_menus_global, config
        ORDER BY position
    ),
    
    -- Prepares a list of submenu lines.
    
    menu_lines AS (
        SELECT
            parent_label,
            position,

            -- Hides menu line if a particular filter is included in state_filter
            -- and its current value does match the specified value
            
            CASE
                WHEN (state_filter ->> '$.authenticated') IS NULL
                  OR state_filter ->> '$.authenticated' = ifnull(authenticated, FALSE) THEN
                    json_object(
                        'title', iif(icon_only IS TRUE, NULL, ifnull(locale ->> ('$.' || label), label)),
                        iif(theme IS NULL, 'icon', 'image'),
                        iif(theme IS NULL, tabler_icon, '/' || (theme ->> ('$.' || label))),
                        'link', link
                    )
            END AS menu_line
        FROM menus, config
        WHERE parent_label IS NOT NULL

        -- Generates and appends the Language submenu lines
        
            UNION ALL
        SELECT
            'Language' AS parent_label,
            position,
            json_object(
                'title',
                iif(hide_language_names IS TRUE, NULL, ifnull(locale ->> ('$.' || label), label)),
                'image', '/' || (iif(theme IS NULL, theme_default, theme) ->> ('$.' || label)),
                'link', '?lang=' || code
            ) AS menu_line
        FROM languages, config
        ORDER BY parent_label, position
    ),
    
    -- Groups menu lines into submenus
    
    menu_lists AS (
        SELECT
            parent_label,
            json_group_array(
                json(menu_line) ORDER BY position
            ) AS menu_list
        FROM menu_lines 
        GROUP BY parent_label
    ),
    
    -- Combines submenus with corresponding top menu lines yielding complete menu_item objects
    
    menu_sets AS (
        SELECT
            position,
            label,
            json_set(json(top_item), '$.submenu', json(menu_list)) AS menu_set
        FROM top_menus, menu_lists
        WHERE top_menus.label = menu_lists.parent_label
        ORDER BY position
    ),
    
    -- Prepares final array of menu_item objects to be used with the "dynamic" component
    
    menu AS (
        SELECT
            json_group_array(json(menu_set) ORDER BY position) AS menu
        FROM menu_sets
    ),

    -- shell_dynamic_static is included for debugging purposes. Call
    -- it to generate "static" SQL for inclusion in an SQLPage script.
    
    shell_dynamic_static AS (
        SELECT
            'SELECT' || x'0A' || '    ''dynamic'' AS component,' || x'0A' ||
            quote(json_pretty(json_object(
                'component', 'shell',
                'title', 'SQLPage',
                'icon', 'database',
                'link', '/',
                'css', '/css/style.css',
                'menu_item', json(menu)
            ))) || ' AS properties' || x'0A0A' AS properties
        FROM menu
    ),
    
    -- Call shell_dynamic if this script is processed directly by SQLPage.
    -- After copy-pasting adjust the input controls in the first CTE.
    
    shell_dynamic AS (
        SELECT
            'dynamic' AS component,
            json_object(
                'component', 'shell',
                'title', 'SQLPage',
                'icon', 'database',
                'link', '/',
                'css', '/css/style.css',
                'menu_item', json(menu)
            ) AS properties
        FROM menu
    )
SELECT * FROM shell_dynamic;
