#include "exception.h"
#include "system.h"
#include "bsp_time.h"
#include "nrf_delay.h"
#include "hal_wearshoes.h"


typedef struct _Task_UseTime
{
	uint32_t task_id;
	uint32_t task_us;
	uint32_t total_us;
} Task_UseTime_t;

static int _report_task_useTime_code = 0;
static bool is_report_task_useTime = false;
static Task_UseTime_t last_round_task_max_useTime = {0xFFFFFFFF,0,0},cur_round_task_max_useTime = {0xFFFFFFFF,0,0},all_round_task_max_useTime = {0xFFFFFFFF,0,0};

//系统函数
void FPS_process(void)
{
	#if DEBUG_FPS
	static uint32_t tem1 = 0;
	static uint32_t tem2 = 0;
	static uint32_t fps_max=0;
	static uint32_t cnt_max=0;
	uint32_t fps;
	
	tem2 = NRF_RTC0->COUNTER;
	if(tem2<tem1) tem2 += 16777216;
	fps = (tem2-tem1)/32.768;
	if(fps_max<fps){
		fps_max = fps;
		cnt_max = tem2-tem1;
	}

	static uint32_t tim=0;
	if(TIME_GetTicks()-tim>=5000){ tim = TIME_GetTicks();
		DEBUG_LOG("fps=%dms,cnt=%d\n",fps_max,cnt_max);
		fps_max = 0;
	}
	tem1 = NRF_RTC0->COUNTER;
	#endif
}

//休眠时间 ms
static uint32_t systermSleepTime = 1000;
static uint8_t sleep_num = 0;
static Sleep_cb sleep_cb[sleep_cb_max]={0};
int Sleep_Regist(Sleep_cb cb)
{
	for(uint8_t i=0;i<sleep_cb_max;i++) {
		if(sleep_cb[i]==cb) return -1;
		if(sleep_cb[i]==0){
			sleep_num++;
			sleep_cb[i] = cb;  //回调函数
			return 0;
		}
	}
	DEBUG_LOG("Sleep_Regist too many!\n");
	return -2;
}

void Sleep_Event(void)
{
	for(uint8_t i=0;i<sleep_num;i++) { //DEBUG_LOG("time_cb[%d]=%d\n",i,time_cb[i]);
		if(sleep_cb[i]){
			sleep_cb[i](StandByPower_Interval);  //回调函数
		}
	}
}

static uint8_t wakeup_num = 0;
static Sleep_cb wakeup_cb[wakeup_cb_max]={0};
int Wakeup_Regist(Sleep_cb cb)
{
	for(uint8_t i=0;i<wakeup_cb_max;i++) {
		if(wakeup_cb[i]==cb) return -1;
		if(wakeup_cb[i]==0){
			wakeup_num++;
			wakeup_cb[i] = cb;  //回调函数
			return 0;
		}
	}
//	DEBUG_LOG("Wakeup_Regist too many!\n");
	return -2;
}

void Wakeup_Event(void)
{
	for(uint8_t i=0;i<wakeup_num;i++) { //DEBUG_LOG("time_cb[%d]=%d\n",i,time_cb[i]);
		if(wakeup_cb[i]){
			wakeup_cb[i](systermSleepTime);  //回调函数
		}
	}
}

//app进程管理

static uint8_t process_dex = 0;
static PROCESS_t mProcess[process_max];

int Process_Start(uint16_t peroid,const char *name,PROCESS_cb cb)
{	
	for(uint8_t i=0;i<process_dex;i++){
		if(mProcess[i].cb==cb){	//已经存在
			mProcess[i].enable =1;
			mProcess[i].Peroid = peroid;
			mProcess[i].tim = TIME_GetTicks();
			return 1;
		}
	}
	
	if(process_dex>=process_max) return -1;
	mProcess[process_dex].cb = cb;
	mProcess[process_dex].enable =1;
	mProcess[process_dex].Peroid = peroid;
	mProcess[process_dex].tim = TIME_GetTicks();
	#if ProcessTime_EN
	mProcess[process_dex].name = name;
	#endif
	process_dex++;
//	DEBUG_LOG("process num(%d)\n",process_dex);
	return 0;
}

void Process_Stop(PROCESS_cb cb)
{
	for(uint8_t i=0;i<process_dex;i++){
		if(mProcess[i].cb==cb){	//找到
			mProcess[i].enable = 0;
			mProcess[i].holdon = 0;
			return;
		}
	}
}

void Process_SetHoldOn(PROCESS_cb cb,uint8_t holdon)
{
	for(uint8_t i=0;i<process_dex;i++){
		if(mProcess[i].cb==cb){	//找到
			if(mProcess[i].holdon!=holdon) mProcess[i].holdon = (holdon&0x01);
			return;
		}
	}
}

void Process_UpdatePeroid(PROCESS_cb cb,uint16_t Peroid)
{
	for(uint8_t i=0;i<process_dex;i++){
		if(mProcess[i].cb==cb){	//找到
			   mProcess[i].Peroid = Peroid;
			return;
		}
	}
}

uint16_t Process_GetPeroid(PROCESS_cb cb)
{
	for(uint8_t i=0;i<process_dex;i++){
		if(mProcess[i].cb==cb){	//找到
			   return mProcess[i].Peroid;
		}
	}
	return 0;
}


int Process_App(void)
{
	int ret = 0;
	uint8_t i = 0;
	char buf[256];
	uint32_t task_useTime = 0;
	
	cur_round_task_max_useTime.task_id 	= 0xFFFFFFFF;
	cur_round_task_max_useTime.task_us 	= 0;
	cur_round_task_max_useTime.total_us = 0;

	for(i=0;i<process_dex;i++){
		Except_Get_Cur_Porcess_ID(i);
		if(mProcess[i].enable==0) continue;
		if(mProcess[i].cb){
			#if ProcessTime_EN
			uint32_t useTime = NRF_RTC0->COUNTER;
			#endif
			
			uint32_t cnt1 = NRF_RTC0->COUNTER;
			
			if(mProcess[i].Peroid ==0) mProcess[i].cb();
			else if(TIME_GetTicks()-mProcess[i].tim >= mProcess[i].Peroid ){
				mProcess[i].tim = TIME_GetTicks();
				mProcess[i].cb();
			}
			
			uint32_t cnt2 = NRF_RTC0->COUNTER;
			
			if(cnt2<cnt1) cnt2 += 16777216;
			
			task_useTime = (cnt2-cnt1)/32.768 * 1000;
			
			cur_round_task_max_useTime.total_us += task_useTime;
			
			if(task_useTime > cur_round_task_max_useTime.task_us)
			{
				cur_round_task_max_useTime.task_us = task_useTime;
				cur_round_task_max_useTime.task_id = i;
			}
			
			#if ProcessTime_EN
			if(NRF_RTC0->COUNTER<useTime) useTime = (NRF_RTC0->COUNTER+16777216-useTime);
			else useTime = (NRF_RTC0->COUNTER-useTime);
			useTime = useTime*1000/32.768;
			if(mProcess[i].useTime<useTime)	mProcess[i].useTime = useTime;
			#endif
		}	
	}
	
	if(cur_round_task_max_useTime.task_us > all_round_task_max_useTime.task_us)
	{
		all_round_task_max_useTime.task_us = cur_round_task_max_useTime.task_us;
		all_round_task_max_useTime.task_id = cur_round_task_max_useTime.task_id;
	}
	
	if(is_report_task_useTime)
	{
		sprintf(buf,"code:%d,report useTime:%d,%d,%d,%d,%d,%d,%d,%d\r\n",_report_task_useTime_code, \
		                                                   last_round_task_max_useTime.task_id, \
																											 last_round_task_max_useTime.task_us, \
																											 last_round_task_max_useTime.total_us, \
																											 cur_round_task_max_useTime.task_id, \
																											 cur_round_task_max_useTime.task_us, \
		                                                   cur_round_task_max_useTime.total_us, \
		                                                   all_round_task_max_useTime.task_id, \
		                                                   all_round_task_max_useTime.task_us);
		Except_TxError(EXCEPT_EXCEPTION,buf);
		
		is_report_task_useTime = false;
	}
	
	last_round_task_max_useTime.task_us 	= cur_round_task_max_useTime.task_us;
	last_round_task_max_useTime.total_us 	= cur_round_task_max_useTime.total_us;
	last_round_task_max_useTime.task_id 	= cur_round_task_max_useTime.task_id;
	
	
	for(i=0;i<process_dex;i++){
		if(mProcess[i].holdon){
			ret = 1;	//不能进入低功耗
//		  DEBUG_LOG("%s can no into low power :\n",mProcess[i].name);
		}
	}
	#if ProcessTime_EN
	static uint32_t tem1 = 0;
	static uint32_t tem2 = 0;
	static uint32_t fps_max=0;
	uint32_t fps;
	
	tem2 = NRF_RTC0->COUNTER;
	if(tem2<tem1) tem2 += 16777216;
	fps = (tem2-tem1)*1000/32.768;
	if(fps_max<fps){
		fps_max = fps;
	}
	
	static uint32_t tim =0;
	if(TIME_GetTicks()-tim>=DisInterval){ tim = TIME_GetTicks();
		DEBUG_LOG("\n============ Tatol(%d process) : %d us ==========\n",process_dex,fps_max);
		for(i=0;i<process_dex;i++){
			if(mProcess[i].useTime>500)
				DEBUG_LOG("[%d]%s : %d us\n",i,mProcess[i].name,mProcess[i].useTime);
			mProcess[i].useTime = 0;
		}
		DEBUG_LOG("\n",fps_max);
		fps_max = 0;
	}
	tem1 = NRF_RTC0->COUNTER;

	#endif
	return ret;
}

//触发上报上一轮、当前轮、所有轮任务中最大的耗时任务和ID，因为实时性的原因，所以不作保证性发送。
void Process_report_task_useTime(int report_task_useTime_code)
{
	_report_task_useTime_code = report_task_useTime_code;
	is_report_task_useTime = true;
}

//大循环
void USR_Process(void)
{
	//app进程调度
	if(Process_App()==0){	//进入低功耗模式
		Sleep_Event();
		systermSleepTime = rtc_sleep(hal_wearshoes_is_wearshoes());
//		DEBUG_LOG("process_sleep_time:%d\n",process_sleep_time);
		Wakeup_Event();
	}
	
	FPS_process();
	
}


void Process_All_Stop(void)
{
	memset(mProcess,0,sizeof(mProcess));
	process_dex = 0;
}
