/*
 * SPDX-FileCopyrightText: 2019-2025 SiFli Technologies(Nanjing) Co., Ltd
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef LVSF_FONT_H
#define LVSF_FONT_H

#include "lvgl.h"
#include "section.h"
#ifdef LV_USING_FREETYPE_ENGINE
    #include "lv_freetype.h"
#endif /* LV_USING_FREETYPE_ENGINE */

typedef enum
{
    FONT_INTERVAL_COMPACT_WIDTH = 0,
    FONT_INTERVAL_EQUAL_WIDTH = 1,
} lvsf_font_interval_t;

//LVSF_FONT_SIZES only used in lvsf_xxx control.
typedef enum
{
    LVSF_FONT_SMALL = 0,
    LVSF_FONT_NORMAL,
    LVSF_FONT_SUBTITLE,
    LVSF_FONT_TITLE,
    LVSF_FONT_BIG,
    LVSF_FONT_HUGE,
    LVSF_FONT_SUPER,
} lvsf_font_size_t;

//If the customer modifies the font size, the following mapping needs to be modified accordingly
#define lvsf_convert_font_size(size)                            \
  switch(size)                                                  \
  {                                                             \
    case LVSF_FONT_SMALL:     size = FONT_SMALL;      break;    \
    case LVSF_FONT_NORMAL:    size = FONT_NORMAL;     break;    \
    case LVSF_FONT_SUBTITLE:  size = FONT_SUBTITLE;   break;    \
    case LVSF_FONT_TITLE:     size = FONT_TITLE;      break;    \
    case LVSF_FONT_BIG:       size = FONT_BIGL;       break;    \
    case LVSF_FONT_HUGE:      size = FONT_HUGE;       break;    \
    case LVSF_FONT_SUPER:     size = FONT_SUPER;      break;    \
  }

typedef lv_font_t *(* font_bitmap_reg_func)(uint16_t);
extern font_bitmap_reg_func p_font_bitmap_reg_func;
void lv_font_bitmap_register(font_bitmap_reg_func reg_func);
void lv_ext_set_local_font_bitmap(lv_obj_t *obj, lv_color_t color, lv_font_t *font);
void lv_ext_set_local_bitmap(lv_obj_t *obj, uint16_t size, lv_color_t color);

#define lv_ext_set_local_bitmap_font(obj, color, font) \
lv_ext_set_local_font_bitmap(obj, color, (lv_font_t *) &font);

/**
 * @brief  Define font size.
           if freetype is used, FONT_SIZES will be used to register in lvsf_ft_reg.h.
           Customers can modify the font size according to their own needs.
 */
#ifndef FT_SIZE_SELF_DEFINED
typedef enum
{

#if(LV_HOR_RES_MAX > 350 && LV_VER_RES_MAX > 350)
    FONT_SMALL      = 16,
    FONT_NORMAL     = 20,
    FONT_SUBTITLE   = 24,
    FONT_TITLE      = 28,
    FONT_BIGL       = 36,
    FONT_HUGE       = 56,
    FONT_SUPER      = 72, /*not_used. can be opened in LVSF_FREETYPE_FONT_REGISTER */
#else
    FONT_SMALL      = 12,
    FONT_NORMAL     = 16,
    FONT_SUBTITLE   = 20,
    FONT_TITLE      = 24,
    FONT_BIGL       = 28,
    FONT_HUGE       = 56,
    FONT_SUPER      = 72, /*not_used. can be opened in LVSF_FREETYPE_FONT_REGISTER */
#endif
} FONT_SIZES;
#else
#include "ft_size_custom_reg.h"
#endif
lv_font_t *lvsf_get_font_from_size(uint16_t size);

#ifndef LV_USING_FREETYPE_ENGINE

static inline const lv_font_t *LV_EXT_FONT_GET(uint16_t size)
{
    lvsf_convert_font_size(size);

    const lv_font_t *font;

    if (FONT_SMALL == size)
    {
        font = lv_theme_get_font_small(NULL);
    }
    else if (FONT_NORMAL == size)
    {
        font = lv_theme_get_font_normal(NULL);
    }
    else if (FONT_SUBTITLE == size)
    {
        font = lv_theme_get_font_subtitle(NULL);
    }
    else if (FONT_TITLE == size)
    {
        font = lv_theme_get_font_title(NULL);
    }
    else if (FONT_BIGL == size)
    {
        font = lv_theme_get_font_bigl(NULL);
    }
    else
    {
        font = lv_theme_get_font_normal(NULL);
    }

    return font;
}
#else

#define FONT_SECTION_NAME app_font

/**
 * @brief  Freetype font initialize.
           Load all fonts and initialize using the interface provided by freetype lib.
 * @param  init initialize lv_freetype_init or not. (In current version, always false)
 */
void lvsf_font_inital(bool init);

/**
 * @brief  Freetype font deinitialize. Release all freetype font.
 */
void lvsf_font_deinit(void);

/**
 * @brief  set font font_list enable or disable.
 * @param  font_name need set enable/disable font name.
 * @param  enable. 0 : disable; 1 : ex
*/
int lvsf_font_set_enable(char *font_name, int enable);

/**
 * @brief  Traverse font_list and return font name.
 * @param  list previous list, set it to NULL when first call.
 * @param  ex get font_name from ex list or whole list. 0 : whole; 1 : noly ex_font; 2 : only builtin font
*/
char *lvsf_font_trav_ex(rt_list_t **list, int ex);

/**
 * @brief  Load and initial freetype font from external.
 * @Usage  lvsf_font_load_ex && lvsf_font_unload_ex.
 *          1)
 *          lvsf_font_load_ex("/fonts/MiSans_Medium_test.ttf", NULL);    //load /fonts/MiSans_Medium_test.ttf
 *          char *font_name[32] = {"MiSans_Medium_test"};
 *          lvsf_font_set_order(font_name , 1)                           //set MiSans_Medium_test to first pos
 *          lvsf_font_set_enable("MiSans_Medium_test", 1);               //enable MiSans_Medium_test
 *                                                                       //use it....
 *          lvsf_font_unload_ex("MiSans_Medium_test")                    //unload /fonts/MiSans_Medium_test.ttf
 *          2)
 *          lvsf_font_load_ex(NULL, NULL)                                //load all font from ft_get_font_path
 *          char *font_name[32] = {xxx};
 *          lvsf_font_set_order(xxx , 1)                                 //set MiSans_Medium_test to first pos
 *          lvsf_font_set_enable(xxx, 1);                                //enable MiSans_Medium_test
 *          lvsf_font_unload_ex                                          //unload all font from ft_get_font_path
 *          @param  font_path NULL: load all ttf_fonts from ft_get_font_path; else: load inficated font_path ttf.
 * @retval  0: load failed; else return ex_font_num.
 */
int lvsf_font_load_ex(char *font_path, uint16_t *size);

/**
 * @brief  unLoad and de-initial freetype font from external.
 * @param  font_path
 *         1) NULL: unload all external ttf;
 *         2) path/xxx.ttf: unload indicated font_path ttf.
 *         3) path: unload all external ttf of indicated font_path.
 */
void lvsf_font_unload_ex(char *font_path);

/**
 * @brief  Load all freetype font which defined by LVSF_FREETYPE_FONT_REGISTER
 */
void lvsf_font_load(void);

/**
 * @brief  unload all freetype font, clean font link header.
 */
void lvsf_font_unload(void);

/**
 * @brief  Indicated freetype font initialize.
 * @param  indicated_font font name.
 */
void lvsf_font_indicated_inital(const char *indicated_font);

/**
 * @brief  Readjust the font traversal order. Used for setting up different languages.
 *         Place the indicated fonts in font name at the beginning and the rest at the end
 *         Usage:
 *         1) set arab font to front.
 *         char *font_name[32] = {"arab"};
 *         lvsf_font_set_order(font_name, 1);
 *         2) set tiny55_full and arab font to front..
 *         char *font_name[32] = {"tiny55_full", "arab"};
 *         uint16_t font_num = 2;
 *         lvsf_font_set_order(font_name, font_num);
 * @param  font_name Need to adjust to the front font list.
 * @param  font_num  The number of fonts that need to be adjusted, corresponding to font name.
 */
void lvsf_font_set_order(char **font_name, uint16_t font_num);

/**
 * @brief  Readjust the font traversal order.
 *         Place the no indicated fonts in font name at the beginning, the indicted fonts at the end
 *         Usage:
 *         1) set arab font to tail.
 *         char *font_name[32] = {"arab"};
 *         uint16_t font_num = 1;
 *         lvsf_font_set_order_reverse(font_name, font_num);
 *         2) set tiny55_full and arab font to tail..
 *         char *font_name[32] = {"tiny55_full", "arab"};
 *         uint16_t font_num = 2;
 *         lvsf_font_set_order_reverse(font_name, font_num);
 * @param  font_name Need to adjust to the tail.
 * @param  font_num  The number of fonts that need to be adjusted, corresponding to font name.
 */
void lvsf_font_set_order_reverse(char **font_name, uint16_t font_num);

/**
 * @brief  reset font order to default (builtin_font).
 *         1) enable all builtin font;
 *         2) disable all ex_font. but ex_font also is in font_list
 *         lvsf_font_reset_order();
 */
void lvsf_font_reset_order(void);

/**
 * @brief  Set the font size , which font name is font_name.
 *         Place the no indicated fonts in font name at the beginning, the indicted fonts at the end.
 *         Usage:
 *         1) set size of "_tiny55_full" to {20, 24, 28, 32, 46, 48, 64, 80, 100}
 *         char *font_name = "tiny55_full";
 *         int size[] = {20, 24, 28, 32, 46, 48, 64, 80, 100, 0};
 *         lvsf_set_font_size_by_name(font_name, size);
 *         2) set size of all font to {20, 24, 28, 32, 46, 48, 64}
 *         int size[] = {20, 24, 28, 32, 46, 48, 64, 0};
 *         lvsf_set_font_size_by_name(NULL, size);
 *         3) set size of "tiny55_full" to default. (same as lvsf_reset_font_size_by_name("tiny55_full"))
 *         char *font_name = "_tiny55_full";
 *         int size[] = {FONT_SMALL, FONT_NORMAL, FONT_SUBTITLE, FONT_TITLE, FONT_BIGL, FONT_HUGE, FONT_SUPER, 0};
 *         lvsf_set_font_size_by_name(font_name, size);
 * @param  size size Size list which will be reset.
 */
void lvsf_set_font_size_by_name(char *font_name, uint16_t *size);

/**
 * @brief  Set size for the font by font name.
 *         Usage:
 *         1) set size of "tiny55_full" to default.
 *         lvsf_reset_font_size_by_name(font_name);
 * @param  size Size_list.
 * @retval font Font pointer.
 */
void lvsf_reset_font_size_by_name(char *font_name);

LV_FONT_DECLARE(static_font_24);

/**
 * @brief  Traverse all fonts, obtain the corresponding font by size.
 * @param  size size Font size.
 * @retval font Font pointer.
 */
static inline const lv_font_t *LV_EXT_FONT_GET(uint16_t size)
{
    lvsf_convert_font_size(size);
    lv_font_t *font = NULL;
#if 1
    font = lvsf_get_font_from_size(size);
#else
    font = (lv_font_t *) &static_font_24;
#endif
    return (const lv_font_t *) font;
}
#endif

/**
 * @brief  Obtain the corresponding font by font name and size.
 * @param  font_name font_name Font name.
 * @param  size size Font size.
 * @retval font Font pointer.
 */
lv_font_t *lvsf_get_font_by_name(char *font_name, int size);

/**
 * @brief  Obtain the corresponding font size by font.
 * @param  font Font pointer.
 * @retval size Font size.
 */
uint16_t lvsf_get_size_from_font(lv_font_t *font);

/**
 * @brief  Set font size and color for label. Note that this is obtained by automatically traversing the font list.
 *         Usage:
 *         1) set font size for label.
 *         lv_ext_set_local_font(label, FONT_TITLE, LV_COLOR_WHITE);
 * @param  obj label.
 * @param  size Font size.
 * @param  color Font color.
 */
void lv_ext_set_local_font(lv_obj_t *obj, uint16_t size, lv_color_t color);

/**
 * @brief  Set indicated font for label.
 *         Usage:
 *         1) using indicated_font "SourceHanSansCN_Bold".
 *         lv_ext_label_set_indicated_font(label, FONT_TITLE, LV_COLOR_WHITE, "SourceHanSansCN_Bold");
 * @param  obj label.
 * @param  size Font size.
 * @param  color Font color.
 * @param  font_name Font name.
 */
void lv_ext_label_set_indicated_font(lv_obj_t *obj, uint16_t size, lv_color_t color, const char *font_name);

/**
 * @brief  Set font_image for label.
 *         Images can be accessed as text through set_font_image. The image name to be accessed is composed of a font name and Unicode,
 *         Current version can't use. TBD...
 * @param  obj label.
 * @param  size Font size.
 * @param  color Font color.
 * @param  font_name Font name.
 * @param  font_interval Font interval. 0 : obtain width through font, 1 : equal width;
 */
void lv_ext_label_set_font_image(lv_obj_t *obj, uint16_t size, lv_color_t color, const char *font_name, uint8_t font_interval);

/**
 * @brief  Since the font currently in use (unload_font) might be deleted, it is necessary to refresh all the objs again to prevent the objs from being bound to an invalid font.
 * @param  top_obj The topest obj.
 * @param  unload_font The unloaded font.
 */
void lv_ext_reload_font(lv_obj_t *top_obj, const char *unload_font);

/**
 * @brief  Obtain the full name of the TTF font. If there is Chinese text in it, the Chinese text shall have priority.
 * @param  font_name The registered name of the font.
 * @param  full_name The returned full name of the font. Note that this memory needs to be allocated before calling the function..
 * @param  full_name_len The length of the full_name memory. If the length of the returned full name exceeds this length, it should be truncated.
 * @retval 0: success; 1: fail.
 */
int lv_ext_get_font_full_name(char *font_name, char *full_name, uint16_t full_name_len);

/**
 * @brief  Current version can't use. TBD...
 */
void lv_ext_font_reset(void);

/**
 * @brief  get font path
 */
const char *ft_get_font_path(void);

/**
 * @brief  clean dcache
 */
int lv_font_dcache_clean(void *data, uint32_t size);

/**
 * Only used for SOLUTION_RES_BUILT_IN, FONT_USING_FLASH_B
 */
int lv_font_lib_is_in_flash(void *font_lib);

#endif /* LV_EXT_RESOURCE_MANAGER_H_ */
