#include "sr_event.h"

static os_slist_node_t gs_eventListHead = OS_SLIST_INIT(gs_eventListHead);

// 事件对象初始化
int SR_EvtObjInit(SR_EVT_OBJ_T *obj, SR_EVT_T *queue, uint8_t queNum, uint32_t *subTab, uint8_t tabNum)
{
	obj->head = 0;
	obj->tail = 0;
	obj->evtNum = 0;
	obj->queueNum = queNum;
	obj->pQueue = queue;
	obj->subTabSize = tabNum;
	obj->pSubTab = subTab;
	obj->list.next = SR_NULL;

	for (int i = 0; i < EVENT_CSMER_MAX; i++)
		obj->csmTab[i] = SR_NULL;

#ifdef SR_USE_OS
		// 创建互斥量
		// rb->mutex = SR_OsMutexCreate();
		// return (rb->mutex)? SR_OK:SR_FAIL;
#else

	// 添加到list
	os_slist_add(&gs_eventListHead, &obj->list);

	return SR_OK;
#endif
}

// 事件消费者初始化
int SR_EvtCsmInit(SR_EVT_CSM_T *csm, uint8_t csmId, EvtProcCb cb, void *args)
{
	if (!csm)
		return SR_INVALID;
	csm->csmId = csmId;
	csm->cb = cb;
	csm->args = args;

	return 0;
}

// 事件发布
int SR_EvtPub(SR_EVT_OBJ_T *obj, SR_EVT_T evt)
{
	int ret = 0;

	if (!obj)
		return SR_INVALID;

	// 将事件写入queue
	// 上锁

	if (obj->evtNum >= obj->queueNum) // queue已满
	{
		ret = SR_FULL;
		goto _end;
	}

	obj->pQueue[obj->tail] = evt;
	obj->tail = (obj->tail + 1) % obj->queueNum; // 防止非法越界
	obj->evtNum++;

_end:

	// 解锁

	return ret;
}

// 事件订阅
int SR_EvtSub(SR_EVT_CSM_T *csm, SR_EVT_OBJ_T *obj, uint8_t evtId)
{
	// 形参有效性判断
	if (evtId >= obj->subTabSize || csm->csmId >= EVENT_CSMER_MAX)
		return SR_INVALID;

	// csm插入订阅列表
	obj->pSubTab[evtId] |= (1 << csm->csmId);

	// 插入消费者列表
	obj->csmTab[csm->csmId] = csm;

	return 0;
}

// 事件取消订阅
int SR_EvtUnsub(SR_EVT_CSM_T *csm, SR_EVT_OBJ_T *obj, uint8_t evtId)
{
	// 形参有效性判断
	if (evtId >= obj->subTabSize || csm->csmId >= EVENT_CSMER_MAX)
		return SR_INVALID;

	// csm从订阅列表移除
	obj->pSubTab[evtId] &= ~(1 << csm->csmId);

	return 0;
}

// 事件分发
void SR_EvtDispatch(void *args)
{
	os_slist_node_t *pos = SR_NULL; // 当前节点
	SR_EVT_OBJ_T *obj = SR_NULL;
	SR_EVT_T evt;

	// 遍历所有的事件对象obj
	os_slist_for_each(pos, &gs_eventListHead)
	{
		obj = SR_CONTAINER_OF(pos, SR_EVT_OBJ_T, list);

		/*读取queue*/
		if (obj->evtNum == 0)
			continue; // queue空

		// 上锁
		evt = obj->pQueue[obj->head];
		obj->head = (obj->head + 1) % obj->queueNum;
		obj->evtNum--;

		// 解锁

		if (evt.isAssign)
		{
			// 分发给指定消费者
			if (obj->csmTab[evt.csmId]->cb)
				obj->csmTab[evt.csmId]->cb(evt, obj->csmTab[evt.csmId]->args);
		}
		else
		{
			// 分发给所有订阅者
			for (int i = (EVENT_CSMER_MAX - 1); i >= 0; i--)
			{
				if (obj->pSubTab[evt.evtId] & (1 << i))
				{
					if (obj->csmTab[i]->cb)
						obj->csmTab[i]->cb(evt, obj->csmTab[i]->args);
				}
			}
		}
	}
	return;
}

/*以下为全局事件：暂时先放这，后面挪到产品开发包里*/

#define GLB_EVT_QUEUE_NUM 10
SR_EVT_OBJ_T gs_glbEvtObj = {0};
SR_EVT_T gs_glbEvtQueue[GLB_EVT_QUEUE_NUM];
uint32_t gs_glbSubTab[GEVT_MAX]; // 项数事件数量相同

// 全局事件初始化
int SR_AppGlbEvtInit(void)
{

	return SR_EvtObjInit(&gs_glbEvtObj, gs_glbEvtQueue, GLB_EVT_QUEUE_NUM, gs_glbSubTab, GEVT_MAX);
}

// 全局事件发布
int SR_AppGlbEvtPub(SR_EVT_T evt)
{
	return SR_EvtPub(&gs_glbEvtObj, evt);
}

// 全局事件订阅
int SR_AppGlbEvtSub(SR_EVT_CSM_T *csm, uint8_t evtId)
{
	return SR_EvtSub(csm, &gs_glbEvtObj, evtId);
}
