#include <string.h>
#include <qsee_timer.h>

#include "timer.h"
#include "rpmb_storage.h"
#include "QSEE_TZ_debug.h"

uint64_t tz_get_timestamp(void)
{
    uint64_t time = 0;
    static uint64_t prev = 0;
    int i;

    /* qsee_get_uptime returns ms */
    for (i = 0 ; i < 10 ;i++)
    {
        time = qsee_get_uptime();
        if (time >= prev  && time != 0) break;
        TTY_LOG("qsee_get_uptime returned invalid value: prev(0x%x) current(0x%x)", prev, time);
    }

    if(i == 10) {
        TTY_LOG("tz_get_timestamp error prev(0x%x) current(0x%x)", prev, time);
    }
    else {
        prev = time;
    }

    return time;
}

void reset_timer(uint8_t index, uint8_t* buffer)
{
    if (index < 1 || index > TIMER_NUM) {
        return;
    }
    index--;

    buffer[TIMER_FLAG_OFFSET+index] = 0x0;
    memset(buffer+(TIMER_OFFSET + index*TIMER_SIZE), 0x0, TIMER_SIZE);
    TTY_LOG("reset_timer: reset timer[%d] ", index);
}

uint8_t set_timer(uint32_t input, uint8_t* buffer)
{
    int i, j;

    for (i=0; i<TIMER_NUM; i++) {
     if (buffer[TIMER_FLAG_OFFSET+i] == 0) {
         memcpy(buffer+TIMER_OFFSET+i*TIMER_SIZE, &input, TIMER_SIZE);
         buffer[TIMER_FLAG_OFFSET+i] = 1;
         TTY_LOG("set_timer: input = 0x%x index = %d flag = %d", input, i, buffer[TIMER_FLAG_OFFSET+i]);
         return i+1;
     }
    }
 return 0;
}

uint8_t check_timer(uint32_t* next_period, uint8_t* buffer)
{
    uint32_t ref_time;
    uint32_t temp_time;
    int i;

    uint8_t trigger = 0x0;
    *next_period = TZ_ARCOUNTER_MAX_TICK_PERIOD;

    memcpy(&ref_time, buffer+REF_TIME_OFFSET, REF_TIME_SIZE);
    TTY_LOG("check_timer: ref_time = 0x%x ", ref_time);
    for (i=0; i<TIMER_NUM; i++) {
        if (buffer[TIMER_FLAG_OFFSET+i] == 1) {
            memcpy(&temp_time, buffer+TIMER_OFFSET+i*TIMER_SIZE, TIMER_SIZE);
            TTY_LOG("check_timer: temp_time[%d] = 0x%x ", i, temp_time);
            if (temp_time != 0 && ref_time >= temp_time) {
        trigger |= 1<<i;
            }
            else if ((temp_time - ref_time) < *next_period) {
                *next_period = temp_time - ref_time;
            }
        }
    }

    if (*next_period == TZ_ARCOUNTER_MAX_TICK_PERIOD && trigger != 0) {
      *next_period = 10;
    }
    TTY_LOG("check_timer: trigger = 0x%x ", trigger);
    TTY_LOG("check_timer: next_period = %d ", *next_period);

    return trigger;
}

uint32_t get_timer(uint8_t index, uint8_t* buffer)
{
    int i = 0;
    uint32_t ret = 0;

  if (index < 1 || index > TIMER_NUM) {
        return 0;
    }
    index--;

    if (buffer[TIMER_FLAG_OFFSET+index] == 1) {
        memcpy(&ret, buffer+TIMER_OFFSET+index*TIMER_SIZE,TIMER_SIZE);
    }
    TTY_LOG("get_timer: index = %d, ret = 0x%x ", index, ret);

    return ret;
}
