/*
 * Created by jiaqiang.ye@lnxall.com
 *
 * IEC104 Server/Slave
 *
 * 2022/03/02
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>

#include "iec104_server_new.h"
#include "cJSON.h"

unsigned int iec104_uptime(unsigned int * secp,
    unsigned int * nsecp)
{
    struct timespec spec;

    spec.tv_sec = 0;
    spec.tv_nsec = 0;
    clock_gettime(CLOCK_BOOTTIME, &spec);
    if (secp != NULL)
        *secp = (unsigned int) spec.tv_sec;
    if (nsecp != NULL)
        *nsecp = (unsigned int) spec.tv_nsec;
    return (unsigned int) spec.tv_sec;
}

uint64_t iec104_upmsec(uint64_t * msecp)
{
    uint64_t ret;
    unsigned int sec, nsec;
    sec = nsec = 0;
    iec104_uptime(&sec, &nsec);
    ret = (uint64_t) sec;
    ret *= 1000;
    ret += (uint64_t) (nsec / 1000000);
    if (msecp != NULL)
        *msecp = ret;
    return ret;
}

static int iec104_mutex_cond_init(pthread_mutex_t * pmtx,
    pthread_cond_t * pcond)
{
    int ret;

    ret = pthread_mutex_init(pmtx, NULL);
    if (ret != 0)
        return -1;
    ret = lnxall_condvar_init(pcond);
    if (ret != 0)
        return -2;
    return 0;
}

struct iec104_var * iec104_server_new_init(void)
{
    int ret, idx, objcnt;
    struct iec104_var * ivar = NULL;

    ivar = (struct iec104_var *) calloc(0x1, sizeof(*ivar));
    if (ivar == NULL) {
        fprintf(stderr, "Error, failed to calloc memory: %d\n", sizeof(*ivar));
        fflush(stderr);
        return NULL;
    }

    /* initialize mutex lock and condition variable */
    ret = iec104_mutex_cond_init(&ivar->thread_lock, &ivar->thread_cond);
    if (ret < 0) {
        fprintf(stderr, "Error, failed to initialize mutex/cond: %d\n", ret);
        fflush(stderr);
        goto err0;
    }

    return ivar;
err0:
    free(ivar);
    fputs("Error, failed to load configs!\n", stderr);
    fflush(stderr);
    return NULL;
}
