#ifndef __MW_CONFIG_H__
#define __MW_CONFIG_H__
#include "mw_config_enum.h"
#include "mw_config_struct.h"
#include "list.h"
#include "mw_storage.h"

#define CFG_MAGIC_DEFAULT       0xdefa0505
#define CFG_ID_NUM  CFG_APP_ID_NUMBER
#define MW_SET_SAME (0x0000FEFEU)

#define CFG_DEFAULT_BRATECTRL_TYPE CFG_VIDEO_CODEC_BRATECTRL_TYPE_VBR

typedef enum
{
    CFG_GROUP_BASE = 0,
    CFG_GROUP_SYSTEM,
    CFG_GROUP_COMMON,
    CFG_GROUP_VIDEO,		
    CFG_GROUP_PHOTO,
    CFG_GROUP_AUDIO,
    CFG_GROUP_IMAGE,
    CFG_GROUP_OTHER,
    CFG_GROUP_APP,
    CFG_GROUP_NUM
}Mw_CfgGroup_Type_e;

typedef enum
{
    CFG_BASE_ID_LICENSE = 0,
    CFG_BASE_ID_FACTORY_MODE,
    CFG_BASE_ID_ACTIVE_TIME,
    CFG_BASE_ID_FACTORY_AGING,
    CFG_BASE_ID_PRODUCT_UUID,
    CFG_BASE_ID_PRODUCT_SERIAL,
    CFG_BASE_ID_NUMBER
}Mw_CfgBase_ID_e;

typedef enum
{
    CFG_SYSTEM_ID_WIFI = CFG_BASE_ID_NUMBER,
    CFG_SYSTEM_ID_BLUETOOTH,
    CFG_SYSTEM_ID_USB,
    CFG_SYSTEM_ID_SENSOR,
    CFG_SYSTEM_ID_BATTERY,
    CFG_SYSTEM_ID_LED,
    CFG_SYSTEM_ID_BUTTON,

    CFG_SYSTEM_ID_NUMBER
}Mw_CfgSystem_ID_e;

typedef enum
{
    CFG_COMMON_ID_CAMMODE = CFG_SYSTEM_ID_NUMBER,

    CFG_COMMON_ID_NUMBER
}Mw_CfgCommon_ID_e;

typedef enum
{
    CFG_VIDEO_ID_RECORD_STREAM = CFG_COMMON_ID_NUMBER,
    CFG_VIDEO_ID_RECORD_SPEC,
    CFG_VIDEO_ID_BITRATE,
    CFG_VIDEO_ID_CODEC,
    CFG_VIDEO_ID_BRATECTRL, // 0 FIX, 1 CBR, 2 VBR, 3 SMART_VBR
    
    CFG_VIDEO_ID_NUMBER
}Mw_CfgVideo_ID_e;

typedef enum
{
    CFG_PHOTO_ID_RESOLUTION = CFG_VIDEO_ID_NUMBER,
    CFG_PHOTO_ID_CAPCFG,

    CFG_PHOTO_ID_NUMBER
}Mw_CfgPhoto_ID_e;

typedef enum
{
    CFG_AUDIO_ID_ENCODE = CFG_PHOTO_ID_NUMBER,

    CFG_AUDIO_ID_NUMBER
}Mw_CfgAudio_ID_e;

typedef enum
{
    CFG_IMAGE_ID_BRIGHTNESS = CFG_AUDIO_ID_NUMBER,
    CFG_IMAGE_ID_CONTRAST,
    CFG_IMAGE_ID_SHARPNESS,
    CFG_IMAGE_ID_AAA,
    CFG_IMAGE_ID_ANTI_FLICKER,

    CFG_IMAGE_ID_NUMBER
}Mw_CfgImage_ID_e;

typedef enum
{
    CFG_OTHER_ID_LCD = CFG_IMAGE_ID_NUMBER,
    CFG_OTHER_ID_QCAP,
    
    CFG_OTHER_ID_NUMBER
}Mw_CfgOther_ID_e;

typedef enum
{
    CFG_APP_ID_GUI = CFG_OTHER_ID_NUMBER,

    CFG_APP_ID_NUMBER
}Mw_CfgApp_ID_e;


/* default system part setting table */
#define CFG_SYSPART_DEFAULT_TABLE \
{ \
    /* header */ \
    .header.version                         = 0x00000001, \
    .header.total_size                      = 0, \
    .header.checksum                        = 0, \
\
    /* base info */ \
    .base_info.factory_mode.factory_mode    = 0, \
    .base_info.active_time.active_time      = 0, \
    .base_info.product_sn.sn                = "INSWWYYNXXXXXX", \
    .base_info.license_info.audio_license   = "default", \
\
    /* system info */ \
    .system_info.wifi_info.enable           = 0, \
    .system_info.bt_info.enable             = 0, \
    .system_info.usb_info.enable            = 0, \
    .system_info.sensor_info.type           = 0, \
    .system_info.battery_info.percent       = 0, \
    .system_info.led_info.enable            = 0, \
    .system_info.button_info.enable         = 0, \
\
}

#define CFG_USERPART_DEFAULT_TABLE_COMMON \
{ \
    .mode.cam_mode      = MW_CFG_CAMMODE_VIDEO, \
    .mode.sub_mode      = MW_CFG_CAM_SUBMODE_VID_NORMAL, \
}

#define CFG_USERPART_DEFAULT_TABLE_VIDEO \
{ \
    .stream.rec_stream      = CFG_VIDEO_RECORD_STREAM_BOTH, \
    .spec.resolution        = MW_CFG_VIDEO_RES_3840X2160, \
    .spec.fps               = MW_CFG_VIDEO_FPS_60, \
    .bitrate.value[0]       = 0, /* main stream */ \
    .bitrate.value[1]       = 0, /* sub stream */ \
    .bratectrl.value        = {CFG_DEFAULT_BRATECTRL_TYPE, CFG_DEFAULT_BRATECTRL_TYPE}, /*all default to CBR*/\
    .codec.main_type        = CFG_VIDEO_CODEC_TYPE_H265, \
    .codec.sub_type         = CFG_VIDEO_CODEC_TYPE_H265, \
}

#define CFG_USERPART_DEFAULT_TABLE_PHOTO \
{ \
    .resolution.val      = MW_CFG_CAP_RES_720X1280, \
    .capcfg.capnum       = 1, \
    .capcfg.aebnum       = 1, \
    .capcfg.strmmsk      = 1, \
    .capcfg.pictype      = 8, \
    .capcfg.syncencstart = 0, \
    .capcfg.caponly      = 0, \
    .capcfg.captype      = 1, \
    .capcfg.stopliveview = 1, \
    .capcfg.timelapsemsk = 0, \
}

#define CFG_USERPART_DEFAULT_TABLE_AUDIO \
{ \
    .encode.bits_per_sample = 16,     \
    .encode.aac_bitrate     = 128000, \
    .encode.volume          = 100,    \
    .encode.enable_DMIC     = 0,      \
}

#define CFG_USERPART_DEFAULT_TABLE_IMAGE \
{ \
    .brightness.val     = 0, \
    .contrast.val       = 0, \
    .sharpness.val      = 0, \
    .aaa.exposure_mode  = MW_CFG_AE_EXPMODE_AUTO, \
    .aaa.shutter        = -1000000, \
    .aaa.iso            = 800, \
    .aaa.shutter_limit  = 0.0, \
    .aaa.iso_limit      = 0, \
    .aaa.ev_bias        = 0.0, \
    .aaa.wb_mode        = MW_CFG_AWB_MODE_AUTO, \
    .aaa.wb_temp        = 2000, \
    .anti_flicker.value = MW_CFG_AE_FLICKER_AUTO,\
}

#define CFG_USERPART_DEFAULT_TABLE_OTHER \
{ \
    .lcd_info.time      = 30,   \
    .lcd_info.brightness= 100,  \
    .quick_cap.enable   = 0,    \
}

#define CFG_USERPART_DEFAULT_TABLE_APP \
{ \
    .gui.val            = 0, \
}

/* default user part setting table */
#define CFG_USERPART_DEFAULT_TABLE \
{ \
    /* header */ \
    .header.version         = 0x00000001, \
    .header.total_size      = 0, \
    .header.checksum        = 0, \
\
    .common_info            = CFG_USERPART_DEFAULT_TABLE_COMMON, \
\
    .video_info             = CFG_USERPART_DEFAULT_TABLE_VIDEO, \
\
    .photo_info             = CFG_USERPART_DEFAULT_TABLE_PHOTO, \
\
    .audio_info             = CFG_USERPART_DEFAULT_TABLE_AUDIO,\
\
    .image_info             = CFG_USERPART_DEFAULT_TABLE_IMAGE,\
\
    .other_info             = CFG_USERPART_DEFAULT_TABLE_OTHER,\
\
    .app_info               = CFG_USERPART_DEFAULT_TABLE_APP,\
\
}

/*
 * access structure
 */
typedef uint32_t (*Mw_CfgAccess_f)(void *data, uint32_t size);
typedef uint32_t (*Mw_CfgSetIdCallback_f)(void *data, uint32_t size);
typedef uint32_t (*Mw_CfgUpdateCallback_f)(uint32_t id, void *data, uint32_t size);
typedef uint32_t (*Mw_CfgPrint_f)(uint32_t id, char *name);

typedef struct {
    struct list_head link;
    Mw_CfgSetIdCallback_f cb_func;
}Mw_CfgSetIdCallback_s;

typedef struct
{
    char *name;
    Mw_CfgAccess_f set_func;
    Mw_CfgAccess_f get_func;
    Mw_CfgPrint_f print_func;
    struct list_head cb_func_list;
}Mw_CfgAccess_t;



uint32_t Mw_Cfg_Init(mw_write_cb wb, mw_read_cb rb);
uint32_t Mw_Cfg_GetConfig(uint32_t config_id, void *p_out, uint32_t size);
uint32_t Mw_Cfg_SetConfig(uint32_t config_id, void *p_in, uint32_t size);
uint32_t Mw_Cfg_GetConfig_NoBlock(uint32_t config_id, void *p_out, uint32_t size);   //use carefully
uint32_t Mw_Cfg_SetConfig_NoBlock(uint32_t config_id, void *p_in, uint32_t size);    //use carefully
uint32_t Mw_Cfg_SetCallbackRegister(uint32_t config_id, Mw_CfgSetIdCallback_f cb_func);
uint32_t Mw_Cfg_SetCallbackUnregister(uint32_t config_id, Mw_CfgSetIdCallback_f cb_func);
uint32_t Mw_Cfg_GetGroupInfo(Mw_CfgGroup_Type_e group_id, void *p_out, uint32_t size);
uint32_t Mw_Cfg_SetGroupInfo(Mw_CfgGroup_Type_e group_id, void *p_in, uint32_t size);
/* TDB: need timer to save config regularly */
uint32_t Mw_Cfg_Save(Mw_CfgStorage_Partition_e part);
uint32_t Mw_Cfg_LoadDefault(Mw_CfgStorage_Partition_e part);
uint8_t Mw_Cfg_IsLoadFromDefault(void);
uint32_t Mw_Cfg_PrintAll(void);
uint32_t Mw_Cfg_PrintId(uint32_t id);


/* For unit test */
uint32_t Mw_Cfg_Destroy(Mw_CfgStorage_Partition_e part, Mw_CfgStorage_Region_e region);


void Mw_Cfg_Test();

#endif