/*
 * Created by jiaqiang.ye@lnxall.com
 *
 * MHMP protocol implmentation
 *
 * 2022/03/29
 */

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#include "mhmp.h"

static int loopflag;
static int readfrom_file;
static void mhmp_sighandler(int signo)
{
    loopflag = 0;
    mhmp_write_last_timetag(NULL, 1);
}

static void mhmp_test_buffer(int signo)
{
    (void) signo;
    readfrom_file = 1;
}

int main(int argc, char * argv[])
{
    int ret;
    struct mhmp_var * mvar;
    int portno = TCP_MHMP_PORT;
    const char * ipaddr = TCP_MHMP_SVRIP;
    const char * load_file_path = NULL;

    loopflag = 1;
    readfrom_file = 0;
    if (argc > 1)
        ipaddr = argv[1];
    if (argc > 2) {
        portno = strtol(argv[2], NULL, 0);
        if (portno <= 0 || portno >= 65536) {
            fprintf(stderr, "Error, invalid portno: %s\n", argv[2]);
            fflush(stderr);
            return 1;
        }
    }
    fprintf(stdout, "MHMP server: %s:%d\n", ipaddr, portno);
    fflush(stderr);

    /* register signal handler for SIGUSR1 */
    if (signal(SIGUSR1, mhmp_test_buffer) == SIG_ERR) {
        fprintf(stderr, "Error, failed to register SIGUSR1 handler: %s\n",
            strerror(errno));
        fflush(stderr);
    }

    if (signal(SIGPIPE, SIG_IGN) == SIG_ERR ||
        signal(SIGINT, mhmp_sighandler) == SIG_ERR ||
        signal(SIGTERM, mhmp_sighandler) == SIG_ERR) {
        fprintf(stderr, "Error, failed to register signal handler: %s\n",
            strerror(errno));
        fflush(stderr);
        return 1;
    }

    mvar = mhmp_create(ipaddr, portno);
    if (mvar == NULL)
        return 2;

    ret = mhmp_ipc_init(mvar);
    if (ret < 0) {
        mhmp_destory(mvar);
        fprintf(stderr, "Error, failed to initialize IPC for MHMP: %d\n", ret);
        fflush(stderr);
        return 3;
    }

    ret = mhmp_connect(mvar, NULL, 0, 2500);
    if (ret < 0) {
        mhmp_destory(mvar);
        return 4;
    }

    mhmp_request_history(mvar);

    if (argc > 3)
        load_file_path = argv[3];

    while (loopflag) {
        int pkterr = 0;
        unsigned char * msgbuff = NULL;

        if (readfrom_file && load_file_path) {
            size_t msgsize = 0;
            unsigned char * msgbuf;

            readfrom_file = 0;
            fprintf(stdout, "Reading from file: %s...\n", load_file_path);
            fflush(stdout);
            msgbuf = mhmp_loadfile(argv[3], 512 * 1024, &msgsize);
            if (msgbuf && msgsize > 0)
                mhmp_process_msg(mvar, (const char *) msgbuf, msgsize);
            free(msgbuf);
        }

        /* MHMP periodic chores */
        ret = mhmp_periodic(mvar);
        if (ret < 0)
            break;

        ret = mhmp_recvmsg(mvar, 1000, &pkterr, &msgbuff);
        if (ret < 0)
            break;

        if (ret == 0) {
            if (pkterr) {
                fputs("Warning, packet error!\n", stdout);
                fflush(stdout);
            }
            continue;
        }

        mhmp_process_msg(mvar, (const char *) msgbuff, ret);
        if (msgbuff != NULL)
            free(msgbuff);
    }

    mhmp_write_last_timetag(NULL, 0);
    mhmp_destory(mvar);
    return 0;
}
