#include "task.h"
#include <malloc.h>
#include <string.h>

static Task_t *TaskHead = NULL;
static PlatformTicksFunc_t platformTicksFunc = NULL;

TaskStatus_t TaskInit(PlatformTicksFunc_t ticksFunc) {
    platformTicksFunc = ticksFunc;
    TaskHead = (Task_t *) malloc(sizeof(Task_t));
    memset(TaskHead, 0, sizeof(Task_t));
    TaskHead->enable = false;
    return true;
}

TaskStatus_t TaskCreat(Task_t *task, TaskTime_t time, TaskCnt_t runcnt, Task_Callback_t callback, void *userdata) {
    if (!callback) {
        return false;
    }
    if (task) {
        TaskDel(task);
    }
    task = (Task_t *) malloc(sizeof(Task_t));
    memset(task, 0, sizeof(Task_t));
    task->intervaltime = time;
    task->lasttime = platformTicksFunc() + task->intervaltime;
    task->runcnt = runcnt;
    task->enable = true;
    task->callback = callback;
    task->userdata = userdata;
    task->next = NULL;
    return TaskAdd(task);;
}

TaskStatus_t TaskAdd(Task_t *task) {
    if (task == NULL) {
        return false;
    }
    Task_t *p = TaskHead;
    while (p->next != NULL) {
        p = p->next;
    }
    p->next = task;
    return true;
}

TaskStatus_t TaskDel(Task_t *task) {
    if (task == NULL) {
        return false;
    }
    Task_t *p = TaskHead;
    Task_t *prev = NULL;
    while (p->next != NULL) {
        //保存当前节点的前一个节点的指针
        prev = p;
        //然后让当前的指针继续往后移动
        p = p->next;
        //判断,找到了要删除的数据
        if (p == task) {
            //两种情况,一种是普通节点,还有一种是尾节点
            if (p->next != NULL)  //普通节点的情况
            {
                prev->next = p->next;
                free(p);
                p = NULL;
            } else //尾节点的情况
            {
                prev->next = NULL; //将这个尾节点的上一个节点的指针域指向空
                free(p);
                p = NULL;
            }
            return true;
        }
    }
    return false;
}

TaskStatus_t TaskStart(Task_t *task) {
    if (task == NULL) {
        return false;
    }
    if (task->runcnt == 0) { task->runcnt = 1; }
    task->enable = true;
    task->lasttime = platformTicksFunc() + task->intervaltime;
    return true;
}

TaskStatus_t TaskStop(Task_t *task) {
    if (task == NULL) {
        return false;
    }
    task->enable = false;
    return true;
}

TaskStatus_t TaskSetCnt(Task_t *task, TaskCnt_t runcnt) {
    if (task == NULL) {
        return false;
    }
    task->runcnt = runcnt;
    if (!task->enable && runcnt != 0) task->enable = true;
    return true;
}

TaskStatus_t TaskSetTime(Task_t *task, TaskTime_t time) {
    if (task == NULL) {
        return false;
    }
    task->intervaltime = time;
    return true;
}

TaskStatus_t TaskRun(void) {
    Task_t *p = TaskHead;
    while (p != NULL) {
        if (p->enable == true && platformTicksFunc() >= p->lasttime) {
            if (p->runcnt == 0) {
                p->enable = false;
                p->lasttime = 0;
                continue;
            }
            if (p->callback) {
                p->callback(p, p->userdata);
                p->lasttime = platformTicksFunc() + p->intervaltime;
            }
            if (p->runcnt > 0) {
                p->runcnt--;
            }
        }
        p = p->next;
    }
    return true;
}