#include "app_config.h"
#include "asm/charge.h"
#include "asm/pwm_led.h"
#include "asm/power_interface.h"
#include "ui_manage.h"
#include "system/event.h"
#include "system/app_core.h"
#include "system/includes.h"
#include "app_action.h"
#include "asm/wdt.h"
#include "app_power_manage.h"
#include "app_chargestore.h"
#include "btstack/avctp_user.h"
#include "app_action.h"
#include "app_main.h"
#include "bt_tws.h"
#include "usb/otg.h"
#include "bt_common.h"
#include "app_task.h"
#include "ui/ui_api.h"

#define LOG_TAG_CONST       APP_CHARGE
#define LOG_TAG             "[APP_CHARGE]"
#define LOG_ERROR_ENABLE
#define LOG_DEBUG_ENABLE
#define LOG_INFO_ENABLE
/* #define LOG_DUMP_ENABLE */
#define LOG_CLI_ENABLE
#include "debug.h"
extern int lcd_sleep_ctrl(u8 enter);
extern void sys_enter_soft_poweroff(void *priv);
extern void gSensor_wkupup_enable(void);
extern void gSensor_wkupup_disable(void);
extern u32 dual_bank_update_exist_flag_get(void);
extern u32 classic_update_task_exist_flag_get(void);
extern int get_need_trim_flag();
extern void watch_reboot_or_shutdown(u8 flag, u8 erase);
#if TCFG_CHARGE_ENABLE

#define TCFG_CHARGE_CHECK_SET_LDOIN_PINR

static u8 charge_full_flag = 0;
#if TCFG_TEST_BOX_ENABLE
static int ldo5v_keep_timer = 0;
#endif
#if TCFG_RECHARGE_ENABLE
static int recharge_timer = 0;
#endif

extern void power_event_to_user(u8 event);

#if TCFG_RECHARGE_ENABLE
static void recharge_check(void *priv)
{
    if ((adc_get_voltage(AD_CH_VBAT) * 4) < TCFG_RECHARGE_VOLTAGE) {
        sys_timer_del(recharge_timer);
        recharge_timer = 0;
        charge_start();
    }
}

static void recharge_detect_start(void)
{
    if (recharge_timer == 0) {
        recharge_timer = sys_timer_add(NULL, recharge_check, 10000);
    }
}

static void recharge_detect_close(void)
{
    if (recharge_timer) {
        sys_timer_del(recharge_timer);
        recharge_timer = 0;
    }
}
#endif

u8 get_charge_full_flag(void)
{
    return charge_full_flag;
}

void charge_start_deal(void)
{
    log_info("%s\n", __FUNCTION__);

    /* power_set_mode(PWR_LDO15);  //充电切到LDO模式，DCDC模式会直接消耗VBat的电 */

    u8 app = app_get_curr_task();
    if (app == APP_IDLE_TASK) {
        ui_update_status(STATUS_CHARGE_START);
    }
}


static void ldo5v_keep_delay_deal(void *priv)
{
    log_info("%s\n", __func__);

#if TCFG_TEST_BOX_ENABLE
    ldo5v_keep_timer = 0;
    if (chargestore_get_testbox_status()) {
        log_info("testbox online!\n");
        return;
    }
#endif

    u8 app = app_get_curr_task();
    if (app != APP_IDLE_TASK) {
        sys_enter_soft_poweroff((void *)2);
    }

    pwm_led_mode_set(PWM_LED_ALL_OFF);
    os_time_dly(30);
    pwm_led_mode_set(PWM_LED1_ON);
    os_time_dly(40);

    //兼容一些充电仓5v输出慢的时候会导致无法充电的问题
    if (get_lvcmp_det()) {
        log_info("...charge ing...\n");
        cpu_reset();
    }

    log_info("get_charge_online_flag:%d %d\n", get_charge_online_flag(), get_ldo5v_online_hw());
    if (get_ldo5v_online_hw() && get_charge_online_flag()) {
        power_set_soft_poweroff();
    } else {
#if TCFG_CHARGE_OFF_POWERON_NE
        cpu_reset();
#else
#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR
        charge_check_and_set_pinr(1);
#endif
        power_set_soft_poweroff();
#endif
    }
}


/*ldoin电压大于拔出电压(0.6V左右)且小于VBat电压时调用该函数进行一些错误提示或其他处理*/
void ldo5v_keep_deal(void)
{
    log_info("%s\n", __func__);

    //关闭充电
    charge_close();

#if TCFG_RECHARGE_ENABLE
    recharge_detect_close();
#endif

    //插入交换
    power_event_to_user(POWER_EVENT_POWER_CHANGE);

#if TCFG_GSENSOR_ENABLE
    //在舱关闭gSensor
    gSensor_wkupup_disable();
#endif

#if TCFG_LP_TOUCH_KEY_ENABLE
    extern void lp_touch_key_charge_mode_enter();
    lp_touch_key_charge_mode_enter();
#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */

#if TCFG_GX8002_NPU_ENABLE
    extern void gx8002_module_suspend(u8 keep_vddio);
    gx8002_module_suspend(0);
#endif /* #if TCFG_GX8002_NPU_ENABLE */


#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR
    charge_check_and_set_pinr(0);
#endif

    if (get_charge_poweron_en() == 0) {
#if TCFG_CHARGESTORE_ENABLE
        //智能充电舱不处理充电err
        u8 app = app_get_curr_task();
        if (app == APP_IDLE_TASK) {
            ui_update_status(STATUS_CHARGE_LDO5V_OFF);
        }

#else //TCFG_CHARGESTORE_ENABLE

#if defined(TCFG_CHARGE_KEEP_UPDATA) && TCFG_CHARGE_KEEP_UPDATA
        if (dual_bank_update_exist_flag_get() || classic_update_task_exist_flag_get()) {
            return;
        }
#endif

#if TCFG_TEST_BOX_ENABLE
        if (ldo5v_keep_timer == 0) {
            //延时执行避免测试盒通信不上
            ldo5v_keep_timer = sys_timeout_add(NULL, ldo5v_keep_delay_deal, 250);
        }
#else
        ldo5v_keep_delay_deal(NULL);
#endif//TCFG_TEST_BOX_ENABLE
#endif//TCFG_CHARGESTORE_ENABLE
    } else {
        ui_update_status(STATUS_CHARGE_ERR);
    }
}

void charge_full_deal(void)
{
    log_info("%s\n", __func__);

    charge_full_flag = 1;

    charge_close();

#if TCFG_RECHARGE_ENABLE
    recharge_detect_start();
#endif

    if (get_charge_poweron_en() == 0) {
        /* power_set_soft_poweroff(); */
#if TCFG_USER_TWS_ENABLE

#else
        ui_update_status(STATUS_CHARGE_FULL);
#endif
#if (!TCFG_CHARGESTORE_ENABLE)
        vbat_timer_delete();
#endif
    } else {
        ui_update_status(STATUS_CHARGE_FULL);
    }
}

void charge_close_deal(void)
{

    log_info("%s\n", __FUNCTION__);

    power_set_mode(TCFG_LOWPOWER_POWER_SEL);

#if TCFG_USER_TWS_ENABLE
    //在idle的时候才执行充电关闭的UI
    u8 app = app_get_curr_task();
    if (app == APP_IDLE_TASK) {
        ui_update_status(STATUS_CHARGE_LDO5V_OFF);
    }
#endif
}


void charge_ldo5v_in_deal(void)
{
    log_info("%s\n", __FUNCTION__);


#if TCFG_IRSENSOR_ENABLE
    if (get_bt_tws_connect_status()) {
        tws_api_sync_call_by_uuid('T', SYNC_CMD_EARPHONE_CHAREG_START, 300);
    }
#endif

#if TCFG_RECHARGE_ENABLE
    recharge_detect_close();
#endif

    //插入交换
    power_event_to_user(POWER_EVENT_POWER_CHANGE);

    charge_full_flag = 0;

#if TCFG_GSENSOR_ENABLE
    //入舱关闭gSensor
    gSensor_wkupup_disable();
#endif

#if TCFG_LP_TOUCH_KEY_ENABLE
    extern void lp_touch_key_charge_mode_enter();
    lp_touch_key_charge_mode_enter();
#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */

#if TCFG_GX8002_NPU_ENABLE
    extern void gx8002_module_suspend(u8 keep_vddio);
    gx8002_module_suspend(0);
#endif /* #if TCFG_GX8002_NPU_ENABLE */

#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR
    charge_check_and_set_pinr(0);
#endif

#if TCFG_TEST_BOX_ENABLE
    chargestore_clear_testbox_status();
    if (ldo5v_keep_timer) {
        sys_timeout_del(ldo5v_keep_timer);
        ldo5v_keep_timer = 0;
    }
#endif

#if TCFG_CHARGESTORE_ENABLE
    chargestore_shutdown_reset();
#endif

    if (get_charge_poweron_en() == 0) {
#if defined(TCFG_CHARGE_KEEP_UPDATA) && TCFG_CHARGE_KEEP_UPDATA
        if (dual_bank_update_exist_flag_get() || classic_update_task_exist_flag_get()) {
            return;
        }
#endif
        u8 app = app_get_curr_task();
        if (app != APP_IDLE_TASK) {

#if (TCFG_CHARGESTORE_ENABLE && TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV)
            if (!chargestore_check_going_to_poweroff()) {
#endif
                sys_enter_soft_poweroff((void *)1);
#if (TCFG_CHARGESTORE_ENABLE && TCFG_BLE_DEMO_SELECT == DEF_BLE_DEMO_ADV)
            } else {
                log_info("chargestore do poweroff!\n");
            }
#endif
        } else {
            //添加cpu_reset防止刚开机app还是NULL的时候,进这里导致无法进idle充电
            extern int cpu_reset_by_soft();
            if (cpu_reset_by_soft()) {
                charge_start();
            } else {
                cpu_reset();
            }
            wdt_init(WDT_32S);
            log_info("set wdt to 32s!\n");
            goto _check_reset;
        }
    } else {
        charge_start();
        goto _check_reset;
    }
    return;

_check_reset:
    //防止耳机低电时,插拔充电有几率出现关机不充电问题
    if (app_var.goto_poweroff_flag) {
        cpu_reset();
    }
}

void charge_ldo5v_off_deal(void)
{
    log_info("%s\n", __FUNCTION__);

    //拨出交换
    power_event_to_user(POWER_EVENT_POWER_CHANGE);
#if (TCFG_CHARGESTORE_ENABLE && TCFG_USER_TWS_ENABLE)
    if (TWS_ROLE_SLAVE == tws_api_get_role()) {
        chargestore_set_power_level(0xFF);
    }
#endif
    charge_full_flag = 0;

    charge_close();

#if TCFG_RECHARGE_ENABLE
    recharge_detect_close();
#endif

    u8 app = app_get_curr_task();
    if (app == APP_IDLE_TASK) {
        ui_update_status(STATUS_CHARGE_LDO5V_OFF);
    }

#ifdef TCFG_CHARGE_CHECK_SET_LDOIN_PINR
    charge_check_and_set_pinr(1);
#endif

#if TCFG_TEST_BOX_ENABLE
    if (chargestore_get_testbox_status() && !get_total_connect_dev()) {
        log_info("<<<<<<<<<<<<<<testbox out and bt noconn reset>>>>>>>>>>>>>>>\n");
        cpu_reset();
    }
    chargestore_clear_testbox_status();
    if (ldo5v_keep_timer) {
        sys_timeout_del(ldo5v_keep_timer);
        ldo5v_keep_timer = 0;
    }
#endif

#if TCFG_CHARGESTORE_ENABLE
    chargestore_shutdown_reset();
#endif

    if ((get_charge_poweron_en() == 0)) {
        wdt_init(WDT_4S);
        log_info("set wdt to 4s!\n");
#if TCFG_CHARGESTORE_ENABLE
        if (chargestore_get_power_status()) {
#endif
#if TCFG_CHARGE_OFF_POWERON_NE
            log_info("ldo5v off,task switch to BT\n");
            app_var.play_poweron_tone = 0;
#if TCFG_SYS_LVD_EN
            vbat_check_init();
#endif
            if ((app != APP_BT_TASK) && (app_var.goto_poweroff_flag == 0)) {
#if TCFG_SYS_LVD_EN
                if (get_vbat_need_shutdown() == FALSE) {
                    task_switch_to_bt();
                } else {
                    log_info("ldo5v off,lowpower,need enter softpoweroff\n");
                    power_set_soft_poweroff();
                }
#else //TCFG_SYS_LVD_EN
                task_switch_to_bt();
#endif //TCFG_SYS_LVD_EN
            }
#else //TCFG_CHARGE_OFF_POWERON_NE
            log_info("ldo5v off,enter softpoweroff\n");
            power_set_soft_poweroff();
#endif //TCFG_CHARGE_OFF_POWERON_NE
#if TCFG_CHARGESTORE_ENABLE
        } else {
            log_info("ldo5v off,enter softpoweroff\n");
            if (app != APP_IDLE_TASK) {
                sys_enter_soft_poweroff(NULL);//软关机
            } else {
                power_set_soft_poweroff();
            }
        }
#endif
    } else {
#if 1//FAST PLUG CHARGE WHEN POWER OFF
        if (app == APP_IDLE_TASK) {
#if TCFG_CHARGE_OFF_POWERON_NE
            //同时打开开机充电和拔出开机
            wdt_init(WDT_4S);
            log_info("set wdt to 4s!\n");

            app_var.play_poweron_tone = 0;//关闭开机提示音，如果需要进开机页面，这里置1
#if TCFG_SYS_LVD_EN
            vbat_check_init();
#endif
            if (!app_var.goto_poweroff_flag) {
#if TCFG_SYS_LVD_EN
                if (get_vbat_need_shutdown() == FALSE) {
                    log_info("ldo5v off,task switch to BT\n");
                    task_switch_to_bt();//默认是直接进表盘的，如需进开机页面，可以切换到app_poweron_task 走开机页面流程;如有模块未初始化，可以在app_idle_task的退出流程进行初始化;
                } else {//电量太低或当前未检查电量时，会走关机流程
                    log_info("ldo5v off,lowpower,need enter softpoweroff\n");
                    power_set_soft_poweroff();
                }
#else //TCFG_SYS_LVD_EN
                task_switch_to_bt();
#endif //TCFG_SYS_LVD_EN
            }

#else
            struct lcd_interface *lcd = lcd_get_hdl();
            if (lcd_sleep_status() == 0) {
                UI_HIDE_CURR_WINDOW();
                lcd_sleep_ctrl(1);
                if (lcd->power_ctrl) {
                    lcd->power_ctrl(false);
                }
            }
            log_info("%s DET:%d", __func__, LVCMP_DET_GET());
            if (!LVCMP_DET_GET()) {
                power_set_soft_poweroff();
            } else {
                if (lcd->power_ctrl) {
                    lcd->power_ctrl(true);
                }
            }
#endif
        }


#else
        if (app == APP_IDLE_TASK) {
            power_set_soft_poweroff();
        }
#endif
    }
#if TCFG_GSENSOR_ENABLE
    //出舱使能gSensor
    gSensor_wkupup_enable();
#endif

#if TCFG_LP_TOUCH_KEY_ENABLE
    extern void lp_touch_key_charge_mode_exit();
    lp_touch_key_charge_mode_exit();
#endif /* #if TCFG_LP_TOUCH_KEY_ENABLE */

#if TCFG_GX8002_NPU_ENABLE
    extern void gx8002_module_resumed();
    gx8002_module_resumed();
#endif /* #if TCFG_GX8002_NPU_ENABLE */
}

int app_charge_event_handler(struct device_event *dev)
{
    int ret = false;
    u8 otg_status = 0;

    switch (dev->event) {
    case CHARGE_EVENT_CHARGE_START:
        UI_WINDOW_PREEMPTION_POP(ID_WINDOW_IDLE);
        UI_WINDOW_PREEMPTION_POSH(ID_WINDOW_IDLE, NULL, NULL, UI_WINDOW_PREEMPTION_TYPE_CHARGE);
        charge_start_deal();
        break;
    case CHARGE_EVENT_CHARGE_CLOSE:
        charge_close_deal();
        UI_WINDOW_PREEMPTION_POP(ID_WINDOW_IDLE);
#if 1
        /*
        	ota后 开机vbat电压低于3.7v时,不能进行power trim
        	此时功耗偏高，耗电速度快

        	可通过提高允许ota的电量(smart->low_battery_level)，避免出现此情况
        	或在ota后充电拔出电压高于3.7v时 复位手表
         */
        if (get_need_trim_flag()) {
            u32 check_vbat = adc_get_voltage_preemption(AD_CH_VBAT) * 4;
            if (check_vbat > 3700) {
                printf("[warning]need_trim_flag is %d,curr vbat: %d mv,please reboot the watch\n", get_need_trim_flag(), check_vbat);
                /*下为复位流程参考*/
                /* watch_reboot_or_shutdown(1, 0); */
            }
        }
#endif
        break;
    case CHARGE_EVENT_CHARGE_FULL:
        charge_full_deal();
        break;
    case CHARGE_EVENT_LDO5V_KEEP:
        ldo5v_keep_deal();
        break;
    case CHARGE_EVENT_LDO5V_IN:
#if (TCFG_APP_PC_EN && (!TCFG_OTG_MODE))
        if (pc_app_check()) {
            UI_WINDOW_PREEMPTION_POSH(ID_WINDOW_PC, NULL, NULL, UI_WINDOW_PREEMPTION_TYPE_CHARGE);
        }
#endif /* #if (TCFG_APP_PC_EN || (!TCFG_OTG_MODE)) */

#if (TCFG_OTG_MODE & (OTG_HOST_MODE|OTG_SLAVE_MODE|OTG_CHARGE_MODE))
        while (1) {
            otg_status = usb_otg_online(0);
            if (otg_status != IDLE_MODE) {
                break;
            }
            os_time_dly(2);
        }
#endif
        if (otg_status != SLAVE_MODE) {
            charge_ldo5v_in_deal();
        }
        break;
    case CHARGE_EVENT_LDO5V_OFF:
#if (TCFG_OTG_MODE & (OTG_HOST_MODE|OTG_SLAVE_MODE|OTG_CHARGE_MODE))
        while (1) {
            otg_status = usb_otg_online(0);
            if (otg_status != IDLE_MODE) {
                break;
            }
            os_time_dly(2);
        }
#endif
        if (otg_status != SLAVE_MODE) {
            charge_ldo5v_off_deal();
        }
#if (TCFG_APP_PC_EN && (!TCFG_OTG_MODE))
        UI_WINDOW_PREEMPTION_POP(ID_WINDOW_PC);
#endif /* #if (TCFG_APP_PC_EN && (!TCFG_OTG_MODE)) */
        break;
    default:
        break;
    }

    return ret;
}

#else

u8 get_charge_full_flag(void)
{
    return 0;
}

#endif

