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

#include "logutils.h"
#include "fileutils.h"
#include "cwg-shared.h"
#include "iowfile.h"

/// @fn void s_termination_handler (int signum)
/// @brief termination signal handler.
/// @param[in] signum signal number
/// @return none
static void s_termination_handler (int signum)
{
    switch (signum) {
#if ! defined(__WIN32) && ! defined(__WIN64)
        case SIGHUP:
#endif
        case SIGINT:
        case SIGTERM:
            fprintf(stderr,"\nsig received[%d]\n",signum);
            g_logutils_interrupt=true;
            break;
        default:
            fprintf(stderr,"\ns_termination_handler: sig not handled[%d]\n",signum);
            break;
    }
}
// End function termination_handler


int main(int argc, char **argv)
{
    int retval=-1;

#if defined(__WIN32) || defined(__WIN64)
    signal(SIGINT,s_termination_handler);
#else
    // configure signal handling
    // for main thread
    struct sigaction saStruct;

    sigemptyset(&saStruct.sa_mask);
    saStruct.sa_flags = 0;
    saStruct.sa_handler = s_termination_handler;
    sigaction(SIGINT, &saStruct, NULL);
#endif

    xcat_config_t cfg_s={
        0,
        0,
        NULL,
        NULL,
        0,
        {0,0},
        {0,0}
    },*cfg=&cfg_s;

    char *file=NULL;
    int i=0;
    if(argc>=1){

        for(i=1;i<argc;i++){

            if(strcmp(argv[i],"h")==0 || strcmp(argv[i],"H")==0){
                xcat_help();
                return 0;
            }else if(sscanf(argv[i],"V%d",&cfg->verbose)==1 ||
                     sscanf(argv[i],"v%d",&cfg->verbose)==1){
            }else if(strcmp(argv[i],"V")==0 ||
                     strcmp(argv[i],"v")==0 ){
                cfg->verbose=1;
            }else if(strstr(argv[i],"r:")!=NULL){
                    char *acpy=strdup(argv[i]);
                    strtok(acpy,":");
                    char *ostr=strtok(NULL,"");
                    char *ocpy=strdup(ostr);
                    char *cur=ocpy;
                    char *opts[4]={NULL,NULL,NULL,NULL};
                    int i=0;
                    while( (isspace((int)*cur)) && (*cur!='\0') )cur++;
                    char *del;
                    while( (del=strstr(cur,","))!=NULL && i<4){
                        opts[i++]=cur;
                        *del='\0';
                        cur=del+1;
                    }
                    if(i<=3)opts[i]=cur;

                    char *mode=opts[0];
                    char *range=opts[1];

                    if(NULL!=mode){
                        if(strstr(mode,"b")!=NULL || strstr(mode,"B")!=NULL)cfg->bflags|=XCAT_MODE_BYTES;
                        if(strstr(mode,"l")!=NULL || strstr(mode,"L")!=NULL)cfg->bflags|=XCAT_MODE_LINES;
                        if(strstr(mode,"i")!=NULL || strstr(mode,"I")!=NULL)cfg->bflags|=(XCAT_TFMT_ISO|XCAT_MODE_TIME);
                        if(strstr(mode,"m")!=NULL || strstr(mode,"M")!=NULL)cfg->bflags|=(XCAT_TFMT_POSIX_MSEC|XCAT_MODE_TIME);
                        if(strstr(mode,"s")!=NULL || strstr(mode,"S")!=NULL)cfg->bflags|=(XCAT_TFMT_POSIX_SEC|XCAT_MODE_TIME);
                        if(strstr(mode,"+")!=NULL )cfg->bflags&=(~XCAT_REF_TAIL);
                        if(strstr(mode,"-")!=NULL )cfg->bflags|=XCAT_REF_TAIL;
                    }
                    if(NULL!=range){
                        cfg->start_tok=strdup(range);
                    }

                    mode=opts[2];
                    range=opts[3];
                    if(NULL!=mode){
                        if(strstr(mode,"b")!=NULL || strstr(mode,"B")!=NULL)cfg->eflags|=XCAT_MODE_BYTES;
                        if(strstr(mode,"l")!=NULL || strstr(mode,"L")!=NULL)cfg->eflags|=XCAT_MODE_LINES;
                        if(strstr(mode,"i")!=NULL || strstr(mode,"I")!=NULL)cfg->eflags|=(XCAT_TFMT_ISO|XCAT_MODE_TIME);
                        if(strstr(mode,"m")!=NULL || strstr(mode,"M")!=NULL)cfg->eflags|=(XCAT_TFMT_POSIX_MSEC|XCAT_MODE_TIME);
                        if(strstr(mode,"s")!=NULL || strstr(mode,"S")!=NULL)cfg->eflags|=(XCAT_TFMT_POSIX_SEC|XCAT_MODE_TIME);
                    }
                    if(NULL!=range){
                        cfg->stop_tok=strdup(range);
                    }

                    OUT_CTTY("opt[%s] bmod[%s] bval[%s] emod[%s] eval[%s]\r\n",ostr,opts[0],opts[1],opts[2],opts[3]);

                    free(acpy);
                    free(ocpy);
             }

            file=argv[i];
        }// for
 
        // use line bmode if none set
        if(XC_MODE(cfg->bflags)==0 ){
            cfg->bflags|=XCAT_MODE_LINES;
        }

        // use bmode if emode unset
        if(XC_MODE(cfg->eflags)==0){
            cfg->eflags|=(XC_MODE(cfg->bflags));
        }

        if( XC_MODE(cfg->eflags)==XCAT_MODE_TIME ) {
            if( XC_MODE(cfg->bflags)==XCAT_MODE_TIME){
                if(XC_TFMT(cfg->eflags)!=XC_TFMT(cfg->bflags)){
                    OUT_CTTY("WARN - end time format mismatch - using start time format\r\n");
                    cfg->eflags&=~(XCAT_TFMT_FLAGS);
                    cfg->eflags|=(XC_TFMT(cfg->bflags));
                }
            }else{
                // emode/bmode different (emode==time)
                // set btime format to match
                cfg->bflags&=~(XCAT_TFMT_FLAGS);
                cfg->bflags|=(XC_TFMT(cfg->eflags));
            }
        }else{
            // emode/bmode different (bmode==time)
            // set etime format to match
            cfg->eflags&=~(XCAT_TFMT_FLAGS);
            cfg->eflags|=(XC_TFMT(cfg->bflags));
        }

        if(XC_MODE_TIME(cfg->bflags) ){
            if(XC_TFMT_ISO(cfg->bflags)){
                cfg->range_t[0]=parse_iso8601(cfg->start_tok,NULL);
            }else{
                if(NULL!=cfg->start_tok)
                if(sscanf(cfg->start_tok,"%"FMT_U64"",&cfg->range_t[0])==1){
                }
            }
        }else{
            if(NULL!=cfg->start_tok)
            if(sscanf(cfg->start_tok,"%"FMT_U32"",&cfg->range_n[0])==1){
            }
        }

        if(XC_MODE_TIME(cfg->eflags) || (XC_MODE(cfg->eflags)==0 && XC_MODE_TIME(cfg->bflags)) ){
            if(XC_TFMT_ISO(cfg->bflags)){
                cfg->range_t[1]=parse_iso8601(cfg->stop_tok,NULL);
            }else{
                if(NULL!=cfg->stop_tok)
                    if(sscanf(cfg->stop_tok,"%"FMT_U64"",&cfg->range_t[1])==1){
                        //                    TRACE();
                    }
            }
        }else{
            if(NULL!=cfg->stop_tok)
                if(sscanf(cfg->stop_tok,"%"FMT_U32"",&cfg->range_n[1])==1){
                    //                TRACE();
                }
        }

    }// if argc

    if(cfg->verbose>0){
        OUT_CTTY("    file: %s\r\n",file);
        OUT_CTTY("  bflags: 0x%08X\r\n",cfg->bflags);
        OUT_CTTY("  eflags: 0x%08X\r\n",cfg->eflags);
        OUT_CTTY("   start: %s\r\n",cfg->start_tok);
        OUT_CTTY("    stop: %s\r\n",cfg->stop_tok);
        OUT_CTTY(" range_t: %"FMT_U64"/%"FMT_U64"\r\n",cfg->range_t[0],cfg->range_t[1]);
        OUT_CTTY(" range_n: %"FMT_U32"/%"FMT_U32"\r\n",cfg->range_n[0],cfg->range_n[1]);
    }

#ifdef WITH_EXTENDED_FCAT
    if(fcat(file,cfg)==ERR_SUCCESS){
            retval=0;
    }
#else
    OUT_CTTY("Requires compilation using WITH_EXTENDED_FCAT (fileutils.h)\r\n");
#endif

    return retval;
}
