
#include "mytimer.h"

TIMER_INFO_T g_timer_info_list[TIMER_MAX_NUM] = {0};
TIMER_MNG_LIST_T g_timer_mng_list={0};
void mytimer_init(void * var)
{
    pthread_rwlock_init(&g_timer_mng_list.timer_lock, NULL);
    g_timer_mng_list.var = var;
    INIT_LIST_HEAD(&g_timer_mng_list.useList);
    INIT_LIST_HEAD(&g_timer_mng_list.unuselist);
    for (int i = 0; i < TIMER_MAX_NUM; i++)
    {
        g_timer_info_list[i].index = i + 1;
        list_add_tail(&g_timer_info_list[i].list, &g_timer_mng_list.unuselist);
    }
}

int mytimer_create(timeFunc func, void *param, USHORT len, USHORT timedelay, TIMER_TYPE_E type)
{
    TIMER_INFO_T *ptimerInfo = NULL;
    if ( (param == NULL && len != 0) || timedelay == 0 || func == NULL)
    {
        return -2;
    }
    pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
    ptimerInfo = list_get_first(&g_timer_mng_list.unuselist, TIMER_INFO_T, list);
    if (ptimerInfo == NULL)
    {
        return -1;
    }
    list_del(&ptimerInfo->list);
    ptimerInfo->delay = timedelay;
    if (len)
    {
        ptimerInfo->paralen = len > TIMER_MAX_PARA_LEN ? TIMER_MAX_PARA_LEN : len;
        memcpy(ptimerInfo->param, param, ptimerInfo->paralen);
    }
    time(&ptimerInfo->tm);
    ptimerInfo->func = func;
    ptimerInfo->use = E_USE;
    ptimerInfo->timerType = type;
    list_add_tail(&ptimerInfo->list, &g_timer_mng_list.useList);
    pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
    return ptimerInfo->index;
}

int mytimer_start( USHORT timerId)
{
    if (timerId > 0 && timerId <= TIMER_MAX_NUM)
    {
        pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
        g_timer_info_list[timerId - 1].startflag = E_USE;
        time(&g_timer_info_list[timerId - 1].tm);
        pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
    }
    else
    {
        return -1;
    }
    return 0;
}

int mytimer_update( USHORT timerId, USHORT timedelay)
{
    if (timerId > 0 && timerId <= TIMER_MAX_NUM)
    {
        pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
        g_timer_info_list[timerId - 1].delay = timedelay;
        pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
    }
    else
    {
        return -1;
    }
    return 0;
}

int mytimer_stop( USHORT timerId)
{
    if (timerId > 0 && timerId <= TIMER_MAX_NUM)
    {
        pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
        g_timer_info_list[timerId - 1].startflag = E_UNUSE;
        pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
    }
    else
    {
        return -1;
    }
    return 0;
}

int mytimer_delete( USHORT timerId)
{
    if (timerId > 0 && timerId <= TIMER_MAX_NUM)
    {
        pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
        if (g_timer_info_list[timerId - 1].use)
        {
            g_timer_info_list[timerId - 1].startflag = E_UNUSE;
            g_timer_info_list[timerId - 1].use = E_UNUSE;
            list_move(&g_timer_info_list[timerId - 1].list, &g_timer_mng_list.unuselist);
            // list_del(&g_timer_info_list[timerId].list);
            // list_add_tail(&g_timer_info_list[timerId].list, &var->timerMng.unuselist);
        }
        pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
    }
    else
    {
        return -1;
    }
    return 0;
}

void mytimer_loop()
{
    TIMER_INFO_T *plist = NULL;
    time_t now;
    time(&now);
    pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
    list_for_each_entry(plist, &g_timer_mng_list.useList, list)
    {
        // printf("plist index:%d-%d ;",plist->index,plist->startflag);
        if (plist->startflag)
        {
            if (now >= plist->tm + plist->delay)
            {
                pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
                plist->func(g_timer_mng_list.var, plist->param, plist->paralen);
                pthread_rwlock_wrlock(&g_timer_mng_list.timer_lock);
                if (plist->timerType == E_TIMER_ONCE)
                {
                    plist->startflag = E_UNUSE;
                }
                else
                {
                    time(&plist->tm);
                }
                break;
            }
        }
    }
    pthread_rwlock_unlock(&g_timer_mng_list.timer_lock);
}
