/**
 *******************************************************************************
 * @file  menu_list.c
 * @brief This file provides firmware functions to manage the menu list.
 @verbatim
   Change Logs:
   Date             Author          Notes
   2022-06-30       CDT             First version
 @endverbatim
 *******************************************************************************
 * Copyright (C) 2022-2023, Xiaohua Semiconductor Co., Ltd. All rights reserved.
 *
 * This software component is licensed by XHSC under BSD 3-Clause license
 * (the "License"); You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                    opensource.org/licenses/BSD-3-Clause
 *
 *******************************************************************************
 */

/*******************************************************************************
 * Include files
 ******************************************************************************/
#include "menu_list.h"

/**
 * @addtogroup Serial_Port_Console
 * @{
 */

/**
 * @defgroup Menu_List Menu List
 * @{
 */

/*******************************************************************************
 * Local type definitions ('typedef')
 ******************************************************************************/

/*******************************************************************************
 * Local pre-processor symbols/macros ('#define')
 ******************************************************************************/

/*******************************************************************************
 * Global variable definitions (declared in header file with 'extern')
 ******************************************************************************/

/*******************************************************************************
 * Local function prototypes ('static')
 ******************************************************************************/

/*******************************************************************************
 * Local variable definitions ('static')
 ******************************************************************************/

/*******************************************************************************
 * Function implementation - global ('extern') and local ('static')
 ******************************************************************************/
/**
 * @defgroup Menu_List_Global_Functions Menu List Global Functions
 * @{
 */

/**
 * @brief  Create menu list.
 * @param  [in] pstcListAttr        Pointer to a @ref stc_menu_list_attr_t structure
 * @param  [in] astcItemTable       Pointer to array @ref stc_menu_item_t structure
 * @retval Pointer to a @ref stc_menu_list_t structure
 */
stc_menu_list_t *Menu_List_Create(const stc_menu_list_attr_t *pstcListAttr, stc_menu_item_t astcItemTable[])
{
    stc_menu_list_t *pstcList = NULL;

    if ((pstcListAttr != NULL) && (astcItemTable != NULL)) {
        pstcList = (stc_menu_list_t *)malloc(sizeof(stc_menu_list_t));
        if (pstcList != NULL) {
            INIT_SLIST_HEAD(&pstcList->stcListNode);
            pstcList->pstcListAttr = pstcListAttr;
            pstcList->pstcItemTable = astcItemTable;
        }
    }

    return pstcList;
}

/**
 * @brief  Destroy menu list.
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @retval None
 */
void Menu_List_Destroy(stc_menu_list_t *pstcList)
{
    if (pstcList != NULL) {
        free(pstcList);
    }
}

/**
 * @brief  Find item by name.
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @param  [in] pcItemName          Pointer to item name
 * @retval Pointer to a @ref stc_menu_item_t structure
 */
stc_menu_item_t *Menu_List_FindItemByName(stc_menu_list_t *pstcList, const char *pcItemName)
{
    stc_menu_item_t *pstcItemTmp;
    stc_menu_item_t *pstcItem = NULL;

    if ((pstcList != NULL) && (pstcList->pstcItemTable != NULL) && (pcItemName != NULL)) {
        for (pstcItemTmp = pstcList->pstcItemTable; (pstcItemTmp->pcName != NULL); pstcItemTmp++) {
            if (0 == strcmp(pstcItemTmp->pcName, pcItemName)) {
                pstcItem = pstcItemTmp;
                break;
            }
        }
    }

    return pstcItem;
}

/**
 * @brief  Find item by ID.
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @param  [in] u16ItemId           Item ID
 * @retval Error code
 */
stc_menu_item_t *Menu_List_FindItemById(stc_menu_list_t *pstcList, uint16_t u16ItemId)
{
    stc_menu_item_t *pstcItemTmp;
    stc_menu_item_t *pstcItem = NULL;

    if ((pstcList != NULL) && (pstcList->pstcItemTable != NULL)) {
        pstcItemTmp = &pstcList->pstcItemTable[u16ItemId];
        if (pstcItemTmp->pcName != NULL) {
            pstcItem = pstcItemTmp;
        }
    }

    return pstcItem;
}

/**
 * @brief  Execute item by name.
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @param  [in] pcItemName          Pointer to item name
 * @retval Error code
 */
int32_t Menu_List_ExecItemByName(stc_menu_list_t *pstcList, const char *pcItemName)
{
    stc_menu_item_t *pstcItem;
    int32_t i32Ret = OPCODE_ERR;

    pstcItem = Menu_List_FindItemByName(pstcList, pcItemName);
    if (pstcItem != NULL) {
        i32Ret = Menu_Item_Exec(pstcItem);
    }

    return i32Ret;
}

/**
 * @brief  Execute item by ID.
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @param  [in] u16ItemId           Item ID
 * @retval Error code
 */
int32_t Menu_List_ExecItemById(stc_menu_list_t *pstcList, uint16_t u16ItemId)
{
    stc_menu_item_t *pstcItem;
    int32_t i32Ret = OPCODE_ERR;

    pstcItem = Menu_List_FindItemById(pstcList, u16ItemId);
    if (pstcItem != NULL) {
        i32Ret = Menu_Item_Exec(pstcItem);
    }

    return i32Ret;
}

/**
 * @brief  Show list attribute(including list and items).
 * @param  [in] pstcList            Pointer to a @ref stc_menu_list_t structure
 * @param  [in] pfnShow             The callback function of show item attribute
 * @retval None
 */
void Menu_List_ShowAttr(stc_menu_list_t *pstcList, int32_t (*pfnShow)(stc_menu_item_t *))
{
    uint8_t u8Id = 0U;
    stc_menu_item_t *pstcItem;

    if ((pstcList != NULL) && (pstcList->pstcItemTable != NULL) && (pfnShow != NULL)) {
        if (pstcList->pstcListAttr->pcName != NULL) {
            printf(pstcList->pstcListAttr->pcDisplayFormatName, pstcList->pstcListAttr->pcName);
        }

        if (pstcList->pstcListAttr->pcListTop != NULL) {
            printf(pstcList->pstcListAttr->pcDisplayFormatListTop, pstcList->pstcListAttr->pcListTop);
        }

        for (pstcItem = pstcList->pstcItemTable; (pstcItem->pcName != NULL) ; pstcItem++) {
            if (pstcList->pstcListAttr->pcItemLeft != NULL) {
                printf(pstcList->pstcListAttr->pcDisplayFormatItemLeft, u8Id++, pstcList->pstcListAttr->pcItemLeft);
            }

            pfnShow(pstcItem);

            if (pstcList->pstcListAttr->pcItemRight != NULL) {
                printf(pstcList->pstcListAttr->pcDisplayFormatItemRight, pstcList->pstcListAttr->pcItemRight);
            }
        }

        if (pstcList->pstcListAttr->pcListBottom != NULL) {
            printf(pstcList->pstcListAttr->pcDisplayFormatListBottom, pstcList->pstcListAttr->pcListBottom);
        }
    }
}

/**
 * @}
 */

/**
 * @}
 */

/**
 * @}
 */

/*******************************************************************************
 * EOF (not truncated)
 ******************************************************************************/
