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

#include "vt.h"
#include "misc.h"
#include "fdset.h"
#include "xio.h"
#include "vbi.h"
#include "lang.h"
#include "cache.h"
#include "ui.h"

int debug = 0;

/* current args for next start() */
static char *geometry;
static char *dpy_name;
static char *vbi_name = NULL;
static struct xio *xio;
static struct vbi *vbi;
static int fine_tune = 1; // auto = 999;
static int erc = 1;
static int newbttv = -1;
static char *progname;
static int txtpid = -1;

static void
usage(FILE *fp, int exitval)
{
    fprintf(fp, "\nUsage: %s [options]\n", prgname);
    fprintf(fp,
	    "\n"
	    "  Valid options:\t\tDefault:\n"
	    "    --help\n"
	    "    --version\n"
	    "    -vbi <vbidev>\t\t/dev/vbi\n"
		"                 \t\t/dev/vbi0\n"
		"                 \t\t/dev/video0\n"
		"                 \t\t/dev/dvb/adapter0/demux0\n"
	    "    -display <dpy>\t\t$DISPLAY\n"
	    "    -geometry <geo>\t\t41x25\n"
	    "    -finetune <-4..4|auto>\t1\n"
	    "    -child <ppp[.ss]>\n"
	    "    [-parent] <ppp[.ss]>\t900\n"
	    //"    -oldbttv\t\t(for bttv <0.5.20)\n"
	    "    -[no]erc\t\t\tenabled\n"
	    "    -[no]bell\t\t\tenabled\n"
	    "    -charset <latin-1/2/koi8-r/\n"
   	    "              iso8859-7>\tlatin-1\n"
	    "    -progname <name>\n"
	    "    -pid <pid>\n"
	    "\n"
	    "  Order is important!  Each page number\n"
	    "  opens a new window with the previously\n"
	    "  given geometry, device, and display.\n"
	    "\n"
	    "  ppp[.ss] stands for a page number and an\n"
	    "  optional subpage number (ie 123.4).  If\n"
	    "  the subpage number is omitted the first\n"
	    "  transmitted subpage is shown.\n"
	    "\n"
	    "  The -child option requires a parent\n"
	    "  window.  So, it must be preceded by\n"
	    "  a parent or another child window.\n"
	    "\n"
	    "  To use the DVB interface, use\n"
	    "  -vbi /dev/dvb/adapter0/demux0\n"
	    "\n"
	    "  The -progname or -pid option specify\n"
	    "  the program or teletext PID if using\n"
	    "  the DVB interface.\n"
	);
    exit(exitval);
}


static int
arg_pgno(char *p, int *subno)
{
    char *end;
    int pgno;

    *subno = ANY_SUB;
    if (*p)
    {
	pgno = strtol(p, &end, 16);
	if ((*end == ':' || *end == '/' || *end == '.') && end[1])
	    *subno = strtol(end + 1, &end, 16);
	if (*end == 0)
	    if (pgno >= 0x100 && pgno <= 0x999)
		if (*subno == ANY_SUB || (*subno >= 0x00 && *subno <= 0x3f7f))
		    return pgno;
    }
    fatal("%s: invalid page number", p);
}


static struct vtwin *
start(int argc, char **argv, struct vtwin *parent, int pgno, int subno)
{
    static int valid_vbi_name = 1;

    if (!valid_vbi_name)
	return parent;

    if (vbi == 0)
	vbi = vbi_open(vbi_name, cache_open(), fine_tune, newbttv, progname, txtpid, 1);
    if (vbi == 0)
    {
	if (vbi_name)
	    error("cannot open device: %s", vbi_name);
    	valid_vbi_name = 0;
    	vbi = open_null_vbi(cache_open());
    }
    if (vbi->cache)
	vbi->cache->op->mode(vbi->cache, CACHE_MODE_ERC, erc);

    if (xio == 0)
	xio = xio_open_dpy(dpy_name, argc, argv);
    if (xio == 0)
	fatal("cannot open display");

    parent = vtwin_new(xio, vbi, geometry, parent, pgno, subno);
    if (parent == 0)
	fatal("cannot create window");

    if (!valid_vbi_name)
    {
	if (vbi_name)
	    send_errmsg(vbi, "cannot open device: %s", vbi_name);
	else
	    send_errmsg(vbi, "cannot open any device", vbi_name);
    }

    return parent;
}


static int
option(int argc, char **argv, int *ind, char **arg)
{
    static struct { char *nam, *altnam; int arg; } opts[] = {
	{ "-vbi", "-dev", 1 },
	{ "-display", "-d", 1 },
	{ "-geometry", "-g", 1 },
	{ "-child", "-c", 1 },
	{ "-editor", "-ed", 0 },
	{ "-parent", "-p", 1 },
	{ "--version", "-v", 0 },
	{ "--help", "-h", 0 },
	{ "-newbttv", "-new", 0 },
	{ "-oldbttv", "-old", 0 },
	{ "-finetune", "-f", 1 },
	{ "-debug", "--debug", 0 },
	{ "-copyright", "-©", 0 },
	{ "-erc", "-e", 0 },
	{ "-noerc", "-ne", 0 },
	{ "-bell", "-b", 0 },
	{ "-nobell", "-nb", 0 },
	{ "-charset", "-latin", 1 },
	{ "-progname", "-pn", 1 },
	{ "-pid", "--pid", 1 },
    };
    int i;

    if (*ind >= argc)
	return 0;

    *arg = argv[(*ind)++];
    for (i = 0; i < NELEM(opts); ++i)
	if (streq(*arg, opts[i].nam) || streq(*arg, opts[i].altnam))
	{
	    if (opts[i].arg)
		if (*ind < argc)
		    *arg = argv[(*ind)++];
		else
		    fatal("option %s requires an argument", *arg);
	    return i+1;
	}

    if (**arg == '-')
    {
	fatal("%s: invalid option", *arg);
	usage(stderr, 1);
    }

    return -1;
}



int
main(int argc, char **argv)
{
    struct vtwin *parent = 0;
    int pgno, subno;
    int opt, ind;
    char *arg;

    setlocale(LC_ALL, "");
    setprgname(argv[0]);

    fdset_init(fds);

    ind = 1;
    while (opt = option(argc, argv, &ind, &arg))
	switch (opt)
	{
	    case 1:	// vbi
		vbi_name = arg;
		vbi = 0;
		parent = 0;
		break;
	    case 2:	// display
		dpy_name = arg;
		xio = 0;
		parent = 0;
		break;
	    case 3:	// geometry
		geometry = arg;
		break;
	    case 4:	// child
		if (parent == 0)
		    fatal("-child requires a parent window");
		pgno = arg_pgno(arg, &subno);
		parent = start(argc, argv, parent, pgno, subno);
		geometry = 0;
		break;
	    case 5:	// editor
		enab_editor = 1;
		break;
	    case 7:	// version
		printf("AleVT Version "VERSION"\n");
		exit(0);
	    case 13:	// copyright
		printf("Copyright 2000 by E. Toernig, froese@gmx.de\n");
		exit(0);
	    case 8:	// help
		usage(stdout, 0);
		break;
	    case 9:	// newbttv
		newbttv = 1;
		break;
	    case 10:	// oldbttv
		newbttv = 0;
		break;
	    case 11:	// finetune
		if (streq(arg, "auto"))
		    fine_tune = 999;
		else
		    fine_tune = strtol(arg, 0, 10);
		break;
	    case 14:	// erc
	    	erc = 1;
		break;
	    case 15:	// noerc
	    	erc = 0;
		break;
	    case 16:	// bell
	    	bell = 1;
		break;
	    case 17:	// nobell
	    	bell = 0;
		break;
	    case 18:	// charset
		if (streq(arg, "latin-1") || streq(arg, "1"))
		    latin1 = LATIN1;
		else if (streq(arg, "latin-2") || streq(arg, "2"))
		    latin1 = LATIN2;
		else if (streq(arg, "koi8-r") || streq(arg, "koi"))
		    latin1 = KOI8;
		else if (streq(arg, "iso8859-7") || streq(arg, "el"))
		    latin1 = GREEK;
		else
		    fatal("bad charset (not latin-1/2/koi8-r/iso8859-7)");
		break;
	    case 12:	// debug
		debug++;
		break;
  	    case 19:    // progname
		progname = arg;
		break;
  	    case 20:    // pid
		txtpid = strtoul(arg, NULL, 0);
		break;
	    case 6:	// parent
	    case -1:	// non-option arg
		pgno = arg_pgno(arg, &subno);
		parent = start(argc, argv, 0, pgno, subno);
		geometry = 0;
		break;
	}

    if (parent == 0)
	start(argc, argv, 0, 0x900, ANY_SUB);

    xio_event_loop();

    exit(0);
}
