#include "user_elect.h"
#include "elect_sw.h"
#include "define.h"
#include "stdarg.h"

tmosTaskID elect_task_id = INVALID_TASK_ID;
static bool elect_start_stat = false;

static uint16_t elect_task_process_event(uint8_t task_id, uint16_t events);
static void elect_01_work_stat(bool stat, elect_work_type_e type);
static void elect_02_work_stat(bool stat, elect_work_type_e type);
static void elect_03_work_stat(bool stat, elect_work_type_e type);
static void elect_04_work_stat(bool stat, elect_work_type_e type);
static void elect_05_work_stat(bool stat, elect_work_type_e type);

static vUser_elect_upload_stat_func xUpload_stat = NULL;
static elect_work_s elect_work[ELECT_COUNT] = {
	{.idx = 0,.stat = true,.type = ELECT_WORK_NULL,.workTime = 0,.func = elect_01_work_stat,},
	{.idx = 1,.stat = true,.type = ELECT_WORK_NULL,.workTime = 0,.func = elect_02_work_stat,},
  {.idx = 2,.stat = true,.type = ELECT_WORK_NULL,.workTime = 0,.func = elect_03_work_stat,},
  {.idx = 3,.stat = true,.type = ELECT_WORK_NULL,.workTime = 0,.func = elect_04_work_stat,},
  {.idx = 4,.stat = true,.type = ELECT_WORK_NULL,.workTime = 0,.func = elect_05_work_stat,},
};

/*******************************************************************************
  * @函数名称   elect_gpio_init
  * @函数说明   GPIO初始化
  * @输入参数  	无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_gpio_init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure = {0};

    ELECT_GPIO_RCC_ENABLE;

    GPIO_InitStructure.GPIO_Pin = ELECT_01_OPEN_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_01_OPEN_GPIO, &GPIO_InitStructure);
    ELECT_01_OPEN_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_01_CLOSE_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_01_CLOSE_GPIO, &GPIO_InitStructure);
    ELECT_01_CLOSE_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_02_OPEN_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_02_OPEN_GPIO, &GPIO_InitStructure);
    ELECT_02_OPEN_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_02_CLOSE_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_02_CLOSE_GPIO, &GPIO_InitStructure);
    ELECT_02_CLOSE_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_03_OPEN_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_03_OPEN_GPIO, &GPIO_InitStructure);
    ELECT_03_OPEN_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_03_CLOSE_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_03_CLOSE_GPIO, &GPIO_InitStructure);
    ELECT_03_CLOSE_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_04_OPEN_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_04_OPEN_GPIO, &GPIO_InitStructure);
    ELECT_04_OPEN_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_04_CLOSE_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_04_CLOSE_GPIO, &GPIO_InitStructure);
    ELECT_04_CLOSE_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_05_OPEN_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_05_OPEN_GPIO, &GPIO_InitStructure);
    ELECT_05_OPEN_OFF;

    GPIO_InitStructure.GPIO_Pin = ELECT_05_CLOSE_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ELECT_05_CLOSE_GPIO, &GPIO_InitStructure);
    ELECT_05_CLOSE_OFF;
}

/*******************************************************************************
  * @函数名称   elect_01_work_stat
  * @函数说明   设置1号电磁锁状态
  * @输入参数  	stat：开或关
               type：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_01_work_stat(bool stat, elect_work_type_e type)
{
	if(type == ELECT_WORK_START)
	{
		if(stat == true)
		{
			ELECT_01_CLOSE_OFF;
			ELECT_01_OPEN_ON;
		}
		else{
			ELECT_01_OPEN_OFF;
			ELECT_01_CLOSE_ON;
		}
	}
	else if(type == ELECT_WORK_END)
	{
		ELECT_01_OPEN_OFF;
		ELECT_01_CLOSE_OFF;
	}
}

/*******************************************************************************
  * @函数名称   elect_02_work_stat
  * @函数说明   设置2号电磁锁状态
  * @输入参数  	stat：开或关
               type：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_02_work_stat(bool stat, elect_work_type_e type)
{
	if(type == ELECT_WORK_START)
	{
		if(stat == true)
		{
			ELECT_02_CLOSE_OFF;
			ELECT_02_OPEN_ON;
		}
		else{
			ELECT_02_OPEN_OFF;
			ELECT_02_CLOSE_ON;
		}
	}
	else if(type == ELECT_WORK_END)
	{
		ELECT_02_OPEN_OFF;
		ELECT_02_CLOSE_OFF;
	}
}

/*******************************************************************************
  * @函数名称   elect_03_work_stat
  * @函数说明   设置3号电磁锁状态
  * @输入参数  	stat：开或关
               type：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_03_work_stat(bool stat, elect_work_type_e type)
{
	if(type == ELECT_WORK_START)
	{
		if(stat == true)
		{
			ELECT_03_CLOSE_OFF;
			ELECT_03_OPEN_ON;
		}
		else{
			ELECT_03_OPEN_OFF;
			ELECT_03_CLOSE_ON;
		}
	}
	else if(type == ELECT_WORK_END)
	{
		ELECT_03_OPEN_OFF;
		ELECT_03_CLOSE_OFF;
	}
}

/*******************************************************************************
  * @函数名称   elect_04_work_stat
  * @函数说明   设置4号电磁锁状态
  * @输入参数  	stat：开或关
               type：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_04_work_stat(bool stat, elect_work_type_e type)
{
	if(type == ELECT_WORK_START)
	{
		if(stat == true)
		{
			ELECT_04_CLOSE_OFF;
			ELECT_04_OPEN_ON;
		}
		else{
			ELECT_04_OPEN_OFF;
			ELECT_04_CLOSE_ON;
		}
	}
	else if(type == ELECT_WORK_END)
	{
		ELECT_04_OPEN_OFF;
		ELECT_04_CLOSE_OFF;
	}
}

/*******************************************************************************
  * @函数名称   elect_05_work_stat
  * @函数说明   设置5号电磁锁状态
  * @输入参数  	stat：开或关
               type：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_05_work_stat(bool stat, elect_work_type_e type)
{
	if(type == ELECT_WORK_START)
	{
		if(stat == true)
		{
			ELECT_05_CLOSE_OFF;
			ELECT_05_OPEN_ON;
		}
		else{
			ELECT_05_OPEN_OFF;
			ELECT_05_CLOSE_ON;
		}
	}
	else if(type == ELECT_WORK_END)
	{
		ELECT_05_OPEN_OFF;
		ELECT_05_CLOSE_OFF;
	}
}

/*******************************************************************************
  * @函数名称   set_elect_work_stat
  * @函数说明   设置电磁锁
  * @输入参数  	idx：锁下标
               stat：工作状态
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void set_elect_work_stat(uint8_t idx, bool stat)
{
  PRINT("No.%d elect = %s\n", idx, (stat == true)?"true":"false");

  electsw_stat_e electswStat = bElectsw_get_stat(idx);

  if(electswStat == ELECTSW_STAT_OPEN && stat == false)
  {
      return;
  }
  else if(electswStat == ELECTSW_STAT_CLOSE && stat == true)
  {
      return;
  }

	elect_work[idx].stat = stat;
	elect_work[idx].type = ELECT_WORK_START;
	elect_work[idx].workTime = 0;
  if(xUpload_stat != NULL)
  {
      // PRINT("No.%d elect upload stat\n", elect->idx);
      xUpload_stat(idx, elect_work[idx].stat, false);
  }
}

/*******************************************************************************
  * @函数名称   elect_work_pro
  * @函数说明   电磁锁执行
  * @输入参数  	elect：对象
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_work_pro(elect_work_s *elect)
{
	if(elect->workTime == 0)
	{
		if(elect->type == ELECT_WORK_START)
		{
			elect->workTime = 50;
			elect->func(elect->stat, ELECT_WORK_START);
			elect->type = ELECT_WORK_END;
		}
		else if(elect->type == ELECT_WORK_END)
		{
			elect->func(elect->type, ELECT_WORK_END);
			elect->type = ELECT_WORK_NULL;
      if(xUpload_stat != NULL)
      {
          // PRINT("No.%d elect upload stat\n", elect->idx);
          xUpload_stat(elect->idx, elect->stat, true);
      }
		}
	}
	else{
		elect->workTime--;
	}
}

/*******************************************************************************
  * @函数名称   elect_task
  * @函数说明   电磁锁任务
  * @输入参数  	无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static void elect_task(void)
{
	for(int i = 0; i < ELECT_COUNT; i++)
	{
    // elect_work[i].idx = i;
		elect_work_pro(&elect_work[i]);
	}
}

/*******************************************************************************
  * @函数名称   elect_task_process_event
  * @函数说明   task的event处理回调函数,需要在注册task时候,传进去
  * @输入参数  	task_id：任务ID
               events：事件
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
static uint16_t elect_task_process_event(uint8_t task_id, uint16_t events)
{
    //event 处理
    if(events & (1 << ELECT_QUEUE_TIME))
    {
        elect_task();
        return (events ^ (1 << ELECT_QUEUE_TIME)); //异或的方式清除该事件运行标志，并返回未运行的事件标志
    }

    if(events & (1 << ELECT_QUEUE_START))
    {
        for(int i = 0; i < ELECT_COUNT; i++)
        {
          set_elect_work_stat(i, elect_work[i].stat);
        }
        return (events ^ (1 << ELECT_QUEUE_START)); //异或的方式清除该事件运行标志，并返回未运行的事件标志
    }

    electsw_task_process_event(task_id, events);

    return 0;
}

/*******************************************************************************
  * @函数名称   elect_start
  * @函数说明   开机电磁锁开启
  * @输入参数  	addr：can地址
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void elect_start(uint8_t addr)
{
	if(elect_start_stat == false && addr > 0)
	{
		elect_start_stat = true;
		bStatus_t stat = tmos_start_task(elect_task_id, (1 << ELECT_QUEUE_START), MS1_TO_SYSTEM_TIME(addr * 500));
	}
}

/*******************************************************************************
  * @函数名称   elect_task_init
  * @函数说明   ELECT任务初始化
  * @输入参数  	无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void elect_task_init(void)
{
    elect_task_id  = TMOS_ProcessEventRegister(elect_task_process_event);
    PRINT("elect_task_id=%d\n", elect_task_id);
    elect_gpio_init();
}

/*******************************************************************************
  * @函数名称   elect_task_start
  * @函数说明   ELECT任务开始
  * @输入参数  	无
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void elect_task_start(void)
{
    bStatus_t stat = tmos_start_reload_task(elect_task_id, (1 << ELECT_QUEUE_TIME), MS1_TO_SYSTEM_TIME(ELECT_INTERVAL));
}

/*******************************************************************************
  * @函数名称   vUser_elect_set_upload_stat_func
  * @函数说明   设置上报电磁锁状态的回调函数
  * @输入参数  	func：函数指针
  * @输出参数   无
  * @返回参数   无
*******************************************************************************/
void vUser_elect_set_upload_stat_func(vUser_elect_upload_stat_func func)
{
    xUpload_stat = func;
}
