#include "hc_config.h"
#include "omw_dbg.h"
#include "omw_svc.h"
#include "omw_rtos.h"
#include "data_xfer.h"
#include "utils/sys_timer.h"
#include "at_commands.h"
#include "omw_cmd.h"

static uint8_t  app_can_sleep;
static uint32_t  intvl_dec;

static struct sys_timer idle_work;

static uint8_t  tx_buf[] = {0xAB, 0x11, 0xCD, 0x22, 0x33, 0xEF, 0x88, 0x66};
static const omw_svc_info_t * p_dx_svc;
uint32_t  deft_conn = 0;

uint8_t g_sleep_timer_flag = 0;						//zhq  note: 
uint8_t g_sleep_change_flag = 0;						//zhq  note: 
uint8_t nosleep_when_wakeup = 0;				//zhq  note: 

//when connected, this function will be called
void hc_app_connected_cb(uint32_t conn_handle, uint16_t cintlv, uint16_t cintlv_min, uint16_t cintlv_max)
{
    deft_conn = conn_handle;
    app_can_sleep = 0;
    intvl_dec = 0;
	
	g_sleep_timer_flag = 0;				//zhq  note: 
}

//when dis-connected, this function will be called
void hc_app_disconnected_cb(uint32_t conn_handle, uint8_t reason)
{
    deft_conn = 0;
    app_can_sleep = 1;
	
	g_sleep_timer_flag = 0;				//zhq  note: 
}

//when rcv data, this function will be called
void hc_app_rx_process_cb(const uint8_t * buf, uint16_t len)
{
    //for example, loop back:
    omw_uart_send(OMW_LOG_UART, buf, len);
    p_dx_svc->nt_tx_cb(deft_conn, buf, len);
}

const uint8_t * hc_app_read_usr_data_cb(uint16_t * len)
{
    *len = sizeof(tx_buf);
    return tx_buf;
}

//run one time
void omw_app_init()
{
//    uint8_t  new_addr[] = {0x34, 0xC3, 0xE2, 0xD8, 0x55, 0x20};
//    omw_svc_set_addr(new_addr);

    app_can_sleep = 1;


    p_dx_svc = omw_data_xfer_svc_get_svc_info();
    p_dx_svc->xfer_reg_cb(hc_app_rx_process_cb, hc_app_read_usr_data_cb);

    /* call omw_svc_start_svc_adv will adv auto, not need to setting more adv/scan rsp params */
    /* if only call omw_svc_add_svc, will not adv auto, you need to call omw_svc_start_adv to start adv */
    /* for example:
        omw_svc_add_svc(svc1);
        omw_svc_add_svc(svc2);

        omw_svc_set_adv_intvl(10, 20);
        omw_set_adv_data(adv_data, 10);
        omw_set_scan_rsp_data(scr_data, 20);

        omw_svc_start_adv();
    */
    omw_svc_start_svc_adv(p_dx_svc);
}

void hc_app_init()
{
    omw_app_init();
}

 static void idle_timeout(struct sys_timer *work)			//zhq  note: 	定时时间到，进入休眠
 {

	if (!nosleep_when_wakeup)
	{
		//outputs("test88");	
		g_sleep_change_flag = 0;					
		app_can_sleep = 1;
	}

 }
 
void hc_fuc_after_wakeup()												//zhq  note: 	唤醒后重置休眠定时
{
		if (g_sleep_timer_flag) 				
		{
			
			nosleep_when_wakeup =  0;
			
			g_sleep_timer_flag = 0;
			//app_can_sleep = 0;
			sys_timer_init(&idle_work, idle_timeout, NULL);								//zhq  note: 初始化休眠定时器
			sys_timer_start(&idle_work, K_SECONDS(30), K_SECONDS(30));		//zhq  note: 打开定时器

		}
}


//run one time after ble base init
//void omw_app_init_after_ble_init()
//{
//    sys_timer_init(&idle_work, idle_timeout, NULL);
//    sys_timer_start(&idle_work, K_SECONDS(10), K_SECONDS(10));
//}

//called by sleep module, check if system can goto sleep
uint8_t omw_app_can_sleep()
{
    return app_can_sleep;
}

#define DFT_SLP_CNT_MIN_INTVL   700     //700*1.25ms
#define DFT_SLP_CNT_MAX_INTVL   800     //800*1.25ms
#define DFT_SLP_LT              80    //10ms
#define DFT_SLP_TO              500    //10ms

uint32_t  counter = 0;
//run every time in main loop
//NOTICE: DO NOT USE INFINITE LOOP in app_main(). DO NOT DELAY LONG TIME in app_main()
//You can use timer to process periodic bussiness
void hc_app_main()
{
	rcv_uart_data();					//zhq  note: 存储接收的数据

	hc_at_cmd_check();				//zhq  note: 处理AT指令
    #ifdef OMW_HAS_SCH
    while(1) {
    #endif
	
        if ((AON_CTRL->WAKEUP_RECORD != 0) &&(g_sleep_change_flag))
        {//is wake-up by gpio
            app_can_sleep = 0;
			
        }
		hc_fuc_after_wakeup();				//zhq  note: 唤醒后重置休眠定时
		
        // if (0 == (counter & (0x8000 - 1))){
            // counter += 2;
//        if (app_can_sleep)
//           printf("i am app main task: %u\n", (unsigned int)counter);
//        // }

        counter++;

        if (deft_conn && (!app_can_sleep) && ((counter & 0xFFFF) == 0))
        {
            struct bt_conn_info info;

            if (!bt_conn_get_info((struct bt_conn *)deft_conn, &info))
            {
				//printf("param: %u, %u, %u, %u\n", (unsigned int)info.le.latency, (unsigned int)info.le.interval,  (unsigned int)info.le.timeout, (unsigned int)intvl_dec);

                // if (info.le.latency != 25)
                if (info.le.interval < 100)
                {
					// while(test_flag == 0);

                    // omw_svc_updata_cnnt_param(deft_conn, info.le.interval, info.le.interval, 25, info.le.timeout);
                    int err = omw_svc_updata_cnnt_param(deft_conn, DFT_SLP_CNT_MIN_INTVL - intvl_dec, DFT_SLP_CNT_MAX_INTVL - intvl_dec, 0, DFT_SLP_TO);

                    if (err)
                    {
                       // printf("conn update failed (err %d).\n", err);
                    }

                    if (intvl_dec < 700)
                    {
                        intvl_dec += 10;

                    }
                }
//                else
//                {
//					if (!nosleep_when_uart_in) 
//					{
//						app_can_sleep = 1;
//					//  printf("ok: %u\n", (unsigned int)intvl_dec);
//					}
//
//                }
            }
        }
    #ifdef OMW_HAS_SCH
        omw_hw_chk_and_en_irq();
    }
    #endif

	// app_can_sleep = 0;
}
