#define TIME_FILENAME   "~/TimeClock/TimeFile.DATA"

#define TET_EOF             0
#define TET_PUNCH_IN        1
#define TET_PUNCH_OUT       2

class TimeEntry
{
    TimeEntry   *next, *last;
    U8           type;
    CDate        datetime;
    U8          *desc;
};

U0 TimeFileRead(TimeEntry *header)
{
    U8          *buf, *ptr;
    I64          type;
    TimeEntry   *tmpt;

    buf = FileRead(TIME_FILENAME);
    if (!buf)
        buf = CAlloc(1);
    QueueInit(header);
    ptr = buf;
    while (type = *ptr++)
    {
        tmpt = CAlloc(sizeof(TimeEntry));
        tmpt->type      = type;
        tmpt->datetime  = *ptr(CDate *)++;
        tmpt->desc      = StrNew(ptr);
        ptr += StrLen(ptr) + 1;
        QueueInsert(tmpt, header->last);
    }
    Free(buf);
}

U0 TimeFileWrite(TimeEntry *header)
{
    U8          *buf, *ptr;
    TimeEntry   *tmpt;
    I64          size = 1; //for EOF

    tmpt = header->next;
    while (tmpt != header)
    {
        size += sizeof(U8) + sizeof(CDate) + StrLen(tmpt->desc) + 1;
        tmpt = tmpt->next;
    }
    buf = MAlloc(size);

    ptr = buf;
    tmpt = header->next;
    while (tmpt != header)
    {
        *ptr+ += tmpt->type;
        *ptr(CDate *)++ = tmpt->datetime;
        StrCopy(ptr, tmpt->desc);
        ptr += StrLen(tmpt->desc) + 1;
        tmpt = tmpt->next;
    }
    *ptr = TET_EOF;
    FileWrite(TIME_FILENAME, buf, size);
    Free(buf);
}

U0 TimeEntriesDel(TimeEntry *header)
{
    TimeEntry *tmpt = header->next, *tmpt1;

    while (tmpt != header)
    {
        tmpt1 = tmpt->next;
        Free(tmpt->desc);
        Free(tmpt);
        tmpt = tmpt1;
    }
    Free(header);
}

public Bool TimeRep(TimeEntry **_header=NULL)
{
    Bool         is_in = FALSE, first = TRUE;
    I64          week, cur_week = -1, week_total;
    TimeEntry   *tmpt, *header = MAlloc(sizeof(TimeEntry));

    if (_header)
        *_header = header;
    TimeFileRead(header);
    tmpt = header->next;
    while (tmpt != header)
    {
        week = tmpt->datetime.date / 7;  //TODO
        if (week != cur_week)
        {
            if (!first)
            {
                if (is_in)
                    week_total += Now;
                "Week Total:%T\n", week_total - local_time_offset;
            }
            else
                first = FALSE;
            cur_week = week;
            week_total = 0;
        }
        if (tmpt->type == TET_PUNCH_IN)
        {
            "$RED$IN ";
            if (!is_in)
                week_total -= tmpt->datetime;
            is_in = TRUE;
        }
        else
        {
            "$RED$OUT";
            if (is_in)
                week_total += tmpt->datetime;
            is_in = FALSE;
        }
        " %D %T:$FG$\n%s\n", tmpt->datetime, tmpt->datetime, tmpt->desc;
        tmpt = tmpt->next;
    }
    if (is_in)
        week_total += Now;
    "$RED$Week Total:%T$FG$\n", week_total - local_time_offset;
    if (!_header)
        TimeEntriesDel(header);
    return is_in;
}

public U0 PunchOut()
{
    TimeEntry *tmpt, *header;

    if (!TimeRep(&header))
        "$BK,1$Already Punched-Out$BK,0$\n";
    else
    {
        tmpt = MAlloc(sizeof(TimeEntry));
        tmpt->type      = TET_PUNCH_OUT;
        tmpt->datetime  = Now;
        "\nEnter Description.\nPress <ESC> when done.\n";
        if (!(tmpt->desc = StrGet(,, SGF_WITH_NEW_LINE)))
            tmpt->desc  = CAlloc(1);
        QueueInsert(tmpt, header->last);
        TimeFileWrite(header);
    }
    TimeEntriesDel(header);
}

public U0 PunchIn()
{
    TimeEntry *tmpt, *header;

    if (TimeRep(&header))
        "$BK,1$Already Punched-In$BK,0$\n";
    else
    {
        tmpt=MAlloc(sizeof(TimeEntry));
        tmpt->type      = TET_PUNCH_IN;
        tmpt->datetime  = Now;
        "\nEnter Description.\nPress <ESC> when done.\n";
        if (!(tmpt->desc = StrGet(,, SGF_WITH_NEW_LINE)))
            tmpt->desc  = CAlloc(1);
        QueueInsert(tmpt, header->last);
        TimeFileWrite(header);
    }
    TimeEntriesDel(header);
}