/*
 * scbus utils to switch card settings.
 *
 * Copyright (C) 2011 Otvos Attila oattila@onebithq.com
 *
 * This is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */


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

#include "config.h"
#include "scbus-config.h"
#include "rs485.h"
#include "util.h"

#define STATUS_GET     1
#define STATUS_PUT     2
#define STATUS_PUT_OK  4

int async_quit_request = 0;

static void usage(char *selfname) {
    fprintf(stderr,"SwitchCard BUS get/put config V1.0\n");
    fprintf(stderr,"(C) 2010 Attila Otvos\n");
    fprintf(stderr,"Web-page: http://onebithq.com/");
    fprintf(stderr,"License type: GPL v2\n");
    fprintf(stderr,"\n");
    fprintf(stderr,"Usage: %s <get|put> <deviceid> [-f|--file <config file name>] [-s|--serial <serial port>] [-b|--baud <baud rate>] [-n|--nocheck] [-h|--help]\n",selfname);
    fprintf(stderr,"\tget:\tget config from device\n");
    fprintf(stderr,"\tput:\tput config to device\n");
    fprintf(stderr,"\t-f|--file:\tconfig file name\n");
    fprintf(stderr,"\t-s|--serial:\tserial port device name (default: %s)\n",DEFAULT_SERIAL);
    fprintf(stderr,"\t-b|--baud:\tserial port baud rate (default: %d)\n",DEFAULT_BAUD);
    fprintf(stderr,"\t-h|--help:\tprint this list\n");
    fprintf(stderr,"\n");
}

static void exit_sighandler(int x){
    static int sig_count=0;

    ++sig_count;
    if(sig_count==6) exit(1);
    if(sig_count<=1)
        switch(x){
        case SIGINT:
        case SIGQUIT:
        case SIGTERM:
        case SIGKILL:
            async_quit_request = 1;
            return;
        }
    exit(1);
}

int main(int argc, char** argv) {
    void* rs485;

    int baud = 0;
    char *device = NULL;
    char *filename = NULL;
    FILE *fh = NULL;
    int deviceid = 0;
    int i,n,t,sec;
    char cmd[8192];
    char buffer[8192];
    unsigned char param[32];
    unsigned char wparam[32];
    int status = 0;
    int confignum = 0;

    for(i=1;i<argc;i++) {
        if((!strcmp(argv[i],"-s") || !strcmp(argv[i],"--serial")) && argv[i+1]) {
            device=argv[++i];
            continue;
        }
        if((!strcmp(argv[i],"-b") || !strcmp(argv[i],"--baud")) && argv[i+1]) {
            baud=atoi(argv[++i]);
            continue;
        }
        if((!strcmp(argv[i],"-f") || !strcmp(argv[i],"--file")) && argv[i+1]) {
            filename=argv[++i];
            continue;
        }
        if((!strcmp(argv[i],"-h") || !strcmp(argv[i],"--help"))) {
            usage(argv[0]);
            exit(1);
        }
        if(!status) {
            if(!strcasecmp(argv[i],"get"))
                status|=STATUS_GET;
            if(!strcasecmp(argv[i],"put"))
                status|=STATUS_PUT;
            if(status)
                continue;
        }
        if(!deviceid) {
            if((deviceid=str2num(argv[i])))
                continue;
        }
        fprintf(stderr,"Error: Illegal parameter: %s\n\n",argv[i]);
        exit(1);
    }
    if(!status) {
        fprintf(stderr,"Error: The get or put mode isn't set.\n");
        exit(1);
    }
    if(!deviceid) {
        fprintf(stderr,"Error: The device ID isn't set.\n");
        exit(1);
    }
    if((status & STATUS_PUT) && !filename) {
        fprintf(stderr,"Error: The file name isn't set.\n");
        exit(1);
    }
    if(status & STATUS_PUT) {
        if(!(fh=fopen(filename,"r"))) {
            fprintf(stderr,"Error: %s (%s)\n",strerror(errno),filename);
            exit(1);
        }
    }
    if(!device)
        device=DEFAULT_SERIAL;
    if(!baud)
        baud=DEFAULT_BAUD;
    if(!(rs485=init_rs485(baud,device))) {
        fprintf(stderr,"Error: %s\n",strerror(errno));
        if(fh)
            fclose(fh);
        exit(1);
    }
    if(!inited_rs485(rs485)) {
        fprintf(stderr,"Error: %s\n",geterror_rs485(rs485));
        done_rs485(rs485);
        if(fh)
            fclose(fh);
        exit(1);
    }

    signal(SIGTERM,exit_sighandler);
    signal(SIGINT,exit_sighandler);
    signal(SIGQUIT,exit_sighandler);

    memset(cmd,0,sizeof(cmd));
    sec=t=0;
    if(status & STATUS_PUT) {
        t=1001;
        status|=STATUS_PUT_OK;
        fprintf(stdout,"Put config to 0x%02X device ",deviceid);
        fflush(stdout);
    }
    while(!async_quit_request) {
        if(isdata_rs485(rs485)) {
            memset(buffer,0,sizeof(buffer));
            while((n=readline_rs485(rs485, buffer, sizeof(buffer)))) {
                if(process_line(buffer, param, sizeof(param))) {
                    if(param[0]=='O' && param[1]==deviceid) {
                        if(status & STATUS_GET) {
                            if(filename && !fh) {
                                if(!(fh=fopen(filename,"w"))) {
                                    fprintf(stderr,"Errror: %s (%s).\n",strerror(errno),filename);
                                    done_rs485(rs485);
                                    exit(1);
                                }
                            }
                            if(fh) {
                                fprintf(fh,"*L%02X%02X%02X%02X%02X%02X\n",deviceid,param[2],param[3],param[4],param[5],param[6]);
                                if(!confignum)
                                    fprintf(stdout,"Get config:");
                                fprintf(stdout," %d",confignum+1);
                                fflush(stdout);
                            } else
                                fprintf(stdout,"*L%02X%02X%02X%02X%02X%02X\n",deviceid,param[2],param[3],param[4],param[5],param[6]);
                            confignum++;
                            if(confignum>=OUTPUTNUMBER)
                                async_quit_request=1;
                        }

                        if(status & STATUS_PUT) {
                            if(param[2]==wparam[2] && param[3]==wparam[3] && param[4]==wparam[4] && param[5]==wparam[5] && param[6]==wparam[6]) {
                                status|=STATUS_PUT_OK;
                                fprintf(stdout,".");
                                fflush(stdout);
                            }
                        }
                    }
                }
                memset(buffer,0,sizeof(buffer));
            }
        }
        if(t>1000 || (status & STATUS_PUT_OK)) {
            t=0;
            sec++;
            if(sec>10) {
                if(fh)
                    fprintf(stdout,"\n");
                fprintf(stderr,"Error: Can't get/put config\n");
                break;
            }
            if(status & STATUS_GET)
                snprintf(buffer,sizeof(buffer),"*Q%02X%02X\n",deviceid,confignum);
            if(status & STATUS_PUT) {
                if(status & STATUS_PUT_OK) {
                    while(!feof(fh)) {
                        memset(buffer,0,sizeof(buffer));
                        n=fgets(buffer,sizeof(buffer),fh);
                        if(feof(fh))
                            break;
                        if(buffer[0]=='\n')
                            continue;
                        if(!process_line(buffer, wparam, sizeof(wparam))) {
                            fprintf(stderr,"Error: skip line: %s",buffer);
                            continue;
                        }
                        if(wparam[0]!='L') {
                            fprintf(stderr,"Error: skip line: %s",buffer);
                            continue;
                        }
                        snprintf(buffer,sizeof(buffer),"*L%02X%02X%02X%02X%02X%02X\n",deviceid,wparam[2],wparam[3],wparam[4],wparam[5],wparam[6]);
                        sec=0;
                        break;
                    }
                    if(feof(fh))
                        break;
                } else {
                    snprintf(buffer,sizeof(buffer),"*L%02X%02X%02X%02X%02X%02X\n\n",deviceid,wparam[2],wparam[3],wparam[4],wparam[5],wparam[6]);
                }
                status&=~STATUS_PUT_OK;
            }
            n=write_rs485(rs485, buffer, strlen(buffer));
        }
        usleep(1000);
        t++;
    }
    if(fh) {
        fprintf(stdout,"\n");
        fclose(fh);
    }
    done_rs485(rs485);
    return 0;
}

