/**
 * Modem main driver.
 *
 * @copyright 2008, Research In Motion Ltd.
 *
 * @version $Id: //depot/rel/dsp/ecall/2/c/testlab/modem.c#1 $
 */

#include <stdlib.h>
#include <stdarg.h>

#include "rimtypes.h"
#include "ipc.h"
#include "error.h"
#include "testlab.h"
#include "option.h"

static char *options[] = {
    "--psap:%s@%s",
    "--psap@%s",
    "--psap",
    "--ivs:%s@%s",
    "--ivs@%s",
    "--ivs",
    "-h",
    "--help",
    NULL
};

#define ARG_MAX_LENGTH  (200)
#define PORT_MAX_LENGTH (200)
#define HOST_MAX_LENGTH (200)

static char p1[ARG_MAX_LENGTH];
static char p2[ARG_MAX_LENGTH];

static char port[PORT_MAX_LENGTH + 1]    = "";
static char host[PORT_MAX_LENGTH + 1]    = "";
static int  mode                         = 0;

static void Usage(char *msg, ...) {
    va_list args;
    va_start(args, msg);

    if (msg != NULL) {
        fprintf(stderr, "Error: ");
        vfprintf(stderr, msg, args);
        fprintf(stderr, "\n");
    }

    fprintf(stderr, "Usage is one of the following forms:\n");
    fprintf(stderr, " modem --psap[[:port]@host]\n");
    fprintf(stderr, "    Runs PSAP modem implementation.\n");
    fprintf(stderr, "    Default port@host is 10003@localhost\n");
    fprintf(stderr, "\n");
    fprintf(stderr, " modem --ivs[[:port]@host]\n");
    fprintf(stderr, "    Runs IVS modem implementation.\n");
    fprintf(stderr, "    Default port@host is 10002@localhost\n");

    va_end(args);
}

static int ProcessArgs(int argc, char *argv[]) {
    int psapCount = 0;
    int ivsCount = 0;

    while (argc-- > 0) {
        int n;

        if (strlen(*argv) >= ARG_MAX_LENGTH) {
            Usage("Argument too long <%s>", *argv);
            return FALSE;
        }
       
        n = option(*argv, options, p1, p2);

        switch (n) {
            case 0: strcpy(port, p1); strcpy(host, p2); psapCount += 1; break;
            case 1: strcpy(host, p1); psapCount += 1; break;
            case 2: psapCount += 1; break;
            case 3: strcpy(port, p1); strcpy(host, p2); ivsCount += 1; break;
            case 4: strcpy(host, p1); ivsCount += 1; break;
            case 5: ivsCount += 1; break;
            case 6:
            case 7: Usage(NULL); return FALSE;
            default: Usage("Invalid option %s", *argv); return FALSE;
        }
        argv++;
    }
    if ((psapCount + ivsCount) < 1) {
        Usage("At least one of --psap --ivs must appear");
        return FALSE;
    }
    if ((psapCount + ivsCount) > 1) {
        Usage("At most one of --psap --ivs can appear");
        return FALSE;
    }
    if (psapCount > 0) mode = 1;
    if (ivsCount  > 0) mode = 2;

    if (strlen(port) <= 0) {
        switch (mode) {
            case 1: strcpy(port, "10003"); break;
            case 2: strcpy(port, "10002"); break;
        }
    }
    if (strlen(host)    <= 0) strcpy(host,    "localhost");

    return TRUE;
}


int main(int argc, char *argv[]) {
    int i;
    BOOL (*run)(void);

    if (ProcessArgs(argc-1, &argv[1])) {
        LogInit(stderr);
        IpcInit();
        switch (mode) {
            case 1:
                PsapInit(host, port);
                run = PsapRun;
                break;
            case 2:
                IvsInit(host, port);
                run = IvsRun;
                break;
            default:
                return 0;
        }
        IpcStart();
        while((*run)());
        IpcStop();
        IpcFinal();
        return 0;
    }

    return -1;
}
