#include "mtimer.h"

// static void pthread_timer_callback(union sigval v)
// {
//     void *priv = (void *)v.sival_ptr;
// }
int mtimer_init_pthread(timer_t timerid, void (*pthread_timer_callback)(union sigval sv), void* priv)
{
    struct sigevent evp;
    memset(&evp, 0, sizeof(evp));
    evp.sigev_value.sival_ptr = priv;
    evp.sigev_notify = SIGEV_THREAD;
    evp.sigev_notify_function = pthread_timer_callback;
    return timer_create(CLOCK_REALTIME, &evp, &timerid);
}

// static void sigaction_timer_callback(int sig, siginfo_t *sinfo, void *ucontext)
// {
//     void *priv = (void *)sinfo.si_value.sival_ptr;
// }
// int mtimer_init_sigaction(timer_t timerid, void (*sigaction_timer_callback)(int sig, siginfo_t *sinfo, void *ucontext), void* priv)
// {
//     /* Set up sigaction. */
//     int sig_no = SIGRTMIN + 1;
//     struct sigaction sa;
//     memset(&sa, 0, sizeof(sa));
//     sa.sa_flags = SA_SIGINFO | SA_RESTART;
//     sa.sa_sigaction = sigaction_timer_callback;
//     sigemptyset (&sa.sa_mask);
//     if (sigaction (sig_no, &sa, NULL) == 0)
//     {
//         struct sigevent evp;
//         memset(&evp, 0, sizeof(evp));
//         evp.sigev_value.sival_ptr = priv;
//         evp.sigev_notify = SIGEV_SIGNAL;
//         evp.sigev_signo = sig_no;
//         return timer_create(CLOCK_REALTIME, &evp, &timerid);
//     }
    
//     return -1;
// }


int mtimer_settime(timer_t timerid, int start_ms, int interval_ms)
{
    struct itimerspec it;
    it.it_value.tv_sec  = start_ms/1000;
    it.it_value.tv_nsec = (start_ms%1000) * 1000;
    it.it_interval.tv_sec  = interval_ms/1000;
    it.it_interval.tv_nsec = (interval_ms%1000) * 1000;
    return timer_settime(timerid, 0, &it, NULL);
}

int mtimer_exit(timer_t timerid)
{
    struct sigaction sa;
    sa.sa_handler = SIG_DFL; // 设置为默认处理
    sigaction(SIGRTMIN+1, &sa, NULL);
    return timer_delete(timerid);
}

/*******************************************************************************************************************/

#define NSEC_PER_SEC 1000000000L

void set_normalized_timespec(struct timespec* ts, time_t sec, int64_t nsec) {
    while (nsec >= NSEC_PER_SEC) {
        nsec -= NSEC_PER_SEC;
        ++sec;
    }
    while (nsec < 0) {
        nsec += NSEC_PER_SEC;
        --sec;
    }
    ts->tv_sec = sec;
    ts->tv_nsec = nsec;
}

struct timespec timespec_add(struct timespec lhs, struct timespec rhs) {
    struct timespec ts_delta;

    set_normalized_timespec(&ts_delta, lhs.tv_sec + rhs.tv_sec, lhs.tv_nsec + rhs.tv_nsec);

    return ts_delta;
}

struct timespec timespec_sub(struct timespec lhs, struct timespec rhs) {
    struct timespec ts_delta;

    set_normalized_timespec(&ts_delta, lhs.tv_sec - rhs.tv_sec, lhs.tv_nsec - rhs.tv_nsec);

    return ts_delta;
}

void timespec_add_ms(struct timespec* ts, long long msec) {
    long long sec = msec / 1000;

    set_normalized_timespec(ts, ts->tv_sec + sec, ts->tv_nsec + (msec - sec * 1000) * 1000 * 1000);
}

/*
 * lhs < rhs:  return < 0
 * lhs == rhs: return 0
 * lhs > rhs:  return > 0
 */
int timespec_compare(const struct timespec* lhs, const struct timespec* rhs) {
    if (lhs->tv_sec < rhs->tv_sec)
        return -1;
    if (lhs->tv_sec > rhs->tv_sec)
        return 1;
    return lhs->tv_nsec - rhs->tv_nsec;
}

long long timespec_to_ms(struct timespec ts) {
    return ((long long)ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
}

long long timespec_to_us(struct timespec ts) {
    return ((long long)ts.tv_sec * 1000000) + (ts.tv_nsec / 1000);
}