/*****************************************************************************/
/*									     */
/*									     */
/*	X patience - main.c						     */
/*									     */
/*	written by Heiko Eissfeldt and Michael Bischoff			     */
/*									     */
/*	24-Feb-1993: First release (0.1)				     */
/*									     */
/*	Last change:							     */
/*	25-Feb-1993: print usage if argument is '-?'			     */
/*	27-Feb-1993: add option -nomem (was: compile-time parameter)	     */
/*	09-Mar-1993: cleanup						     */
/*	14-Mar-1993: accept command name as option for rules		     */
/*									     */
/*									     */
/*****************************************************************************/

#include "xpat.h"
#include "xpatx11.h"

static void usage(const char *arg)
{   fprintf(stderr, "usage: pat [options] [<seed> or <savedgame>]\n");
    fprintf(stderr, "valid options are:\n");
    fprintf(stderr, "-display <display>      set display\n");
    fprintf(stderr, "-geometry <geometry>    set initial geometry\n");
    fprintf(stderr, "-cards <cardset>        set cardset to external file\n");
    fprintf(stderr, "-xpmdir <directory>     for internal cardset: load xpm files\n");
    fprintf(stderr, "-sound <0/1>            enables/disables sound\n");

    fprintf(stderr, "-bg <backgroundcolor>   set background color\n");
    fprintf(stderr, "-cb <cardbackcolor>     set cardback color\n");
    fprintf(stderr, "-markcolor <markcolor>  set color of card marks\n");
    fprintf(stderr, "-markwidth <markwidth>  set width of card marks\n");
    fprintf(stderr, "-bfont <fontname>       set font for buttons\n");
    fprintf(stderr, "-sfont <fontname>       set font for status line\n");
    fprintf(stderr, "-gapsize <gapsize>      set space between cards (0 to 20)\n");
    fprintf(stderr, "\ngame customization:\n");
    fprintf(stderr, "-rules <ruleset>        set rules to HM or Spider or Stairs\n");
    fprintf(stderr, "-slots <slots>          set number of slots (2 to 60)\n");
    fprintf(stderr, "-decks <decks>          set number of decks (1 to 9)\n");
    fprintf(stderr, "-faceup <faceup>        set initial deal parameter (0 to 20)\n");
    fprintf(stderr, "-facedown <facedown>    set initial deal parameter (0 to 20)\n");
    fprintf(stderr, "-jokers <jokers>        set number of jokers (do not use, it's too easy)\n");
    fprintf(stderr, "-flips <flips>          limit number of flips (0 to 999)\n");
    fprintf(stderr, "-turn <turn>            set number of cards to turn (1 to 9)\n");
#if 0	/* for insiders only */
    fprintf(stderr, "-autolayout <0/1>       0: to avoid automatic re-layout at resize time\n");
    fprintf(stderr, "-mem <0/1>              0: do not store card images at full depth internally\n");
    fprintf(stderr, "-by <buttongap>         set button gap y size\n");
    fprintf(stderr, "-bx <buttongap>         set button gap x size\n");
    fprintf(stderr, "-cround <cornersize>    set size of round card corners (0 to 20)\n");
    fprintf(stderr, "-bround <cornersize>    set size of round button corners (0 to 20)\n");
#endif
    if (arg)
 	fprintf(stderr,"argument \"%s\" caused this message\n", arg);
    exit(1);
}

/* enum { String, Number, Bool } argtype; */
#define String 0
#define Number 1
#define Self   2

int main(int argc, char **argv)
{   int i;
    long seed = -1L;
    const char *restoregame = NULL;
    static const char *display = NULL, *cmdname;

    static int slots, faceup, facedown, decks, flips, turn; /* rules customization */
    static int linewidth, cround, bround, gapx, gapy, bx, by, autolayout, mem;
    static int arrw, arrh, jokers, sound = 1;
    static const char *geometry, *ruleset, *cbcolor, *bkcolor = "DarkKhaki";
    static const char *buttonfont, *statusfont, *cardset, *markcolor, *xpmdir;
    static const char *arrowcolor;

static struct option {
    const char *option;
    const char *resource;
    const char *value;
    void *where;
    int type;
    int minval;       /* only for Number */
    int maxval;       /* only for Number */
    const char *cmdarg;
} options[] = {
    /* first option must be -rules */
    { "-rules",	    "Rules",	     "Gypsy",     &ruleset,   String },
    { "-autolayout","AutoLayout",    "1",         &autolayout,Number,  0,  1 },
    { "-mem",       "Mem",           "1",         &mem,       Number,  0,  1 },
    { "-xpmdir",    "XpmDir",        NULL,        &xpmdir,    String },
    { "-cards",     "Cards",         NULL,        &cardset,   String },
    { "-slots",     "Slots",	     NULL,        &slots,     Number, -1, MAXPILES },
    { "-flips",     "Flips",	     NULL,        &flips,     Number, -1,999 },
    { "-turn",      "Turn",	     NULL,        &turn,      Number, -1,  9 },
    { "-decks",     "Decks",         NULL,        &decks,     Number, -1,  9 },
    { "-faceup",    "Faceup",        NULL,        &faceup,    Number, -1, 16 },
    { "-facedown",  "Facedown",      NULL,        &facedown,  Number, -1, 16 },
    { "-jokers",    "Jokers", 	     NULL,        &jokers,    Number, -1, 16 },
    { "-cround",    "CardRound",     NULL,        &cround,    Number, -1, 99 },
    { "-bround",    "ButtonRound",   "4",         &bround,    Number,  0, 20 },
    { "-sound",     "Sound",         "1",         &sound,     Number,  0,  1 },
    { "-bx",        "ButtonGapX",    "4",         &bx,        Number,  0, 99 },
    { "-by",        "ButtonGapY",    "4",         &by,        Number,  0, 99 },
    { "-aw",        "ArrowWidth",    NULL,        &arrw,      Number, -1, 30 },
    { "-ah",        "ArrowHeight",   NULL,        &arrh,      Number, -1, 30 },
    { "-gapx",      "GapX",          "4",         &gapx,      Number,  0, 99 },
    { "-gapy",      "GapY",          "4",         &gapy,      Number,  0, 99 },
    { "-cb",        "CardbackColor", "SlateGrey", &cbcolor,   String },
    { "-bg",   	    "TableColor",    "DarkKhaki", &bkcolor,   String },
    { "-markcolor", "MarkColor",     NULL,        &markcolor, String },
    { "-markwidth", "MarkWidth",     "999",       &linewidth, Number,  1,999 },
    { "-arrowcolor","ArrowColor",    "Gold",      &arrowcolor,String },
    { "-bfont",     "ButtonFont",    NULL,        &buttonfont,String },
    { "-sfont",     "StatusFont",    "fixed",     &statusfont,String },
    { "-geometry",  "Geometry",      NULL,        &geometry,  String },
    { "-display",   NULL,            NULL,        &display,   String }
};
#define NUMOPTIONS      (sizeof(options) / sizeof(options[0]) - 1)

    for (i = 0; i <= NUMOPTIONS; ++i)
        options[i].cmdarg = NULL;

    if (!(cmdname = strrchr(argv[0], '/')))
	cmdname = argv[0];
    else
	++cmdname;
    if (strcmp(cmdname, "xpat"))
	options[0].cmdarg = cmdname;

    for (i = 1; i < argc - 1; ++i) {    /* merge command line options */
	int j;
	if (*argv[i] != '-')
	    break;
	for (j = 0; j <= NUMOPTIONS; ++j) {
	    if (!strcmp(argv[i], options[j].option)) {
		options[j].cmdarg = options[j].type == Self ? "1" : argv[++i];
		break;
	    }
        }
        if (j > NUMOPTIONS)
	    usage(argv[i]);
    }
    if (i < argc) {		/* seed or savegame left */
	if (i != argc - 1)
	    usage(argv[i]);
	if (isdigit(*argv[i])) {
	    seed = atol(argv[i]);
	    if (seed < 0L || seed >= PRANDMAX)
		usage(argv[i]);
	} else
	    if (*argv[i] != '-')
		restoregame = argv[i];
	    else
		usage(argv[i]);
    }
    display = options[NUMOPTIONS].cmdarg;

    init_display(display);		/* connect to X-server */

    for (i = 0; i < NUMOPTIONS; ++i) {  /* get resources from server */
	char *s;
        if (options[i].cmdarg)
	    options[i].value = options[i].cmdarg;
        else if ((s = XGetDefault(dpy, "XPat", options[i].resource)))
	    options[i].value = s;
    }

    for (i = 0; i < NUMOPTIONS; ++i) {  /* value-check Numbers */
	int n;
	struct option *o;
	o = options + i;
        if (o->type == Number) {
	    n = o->value ? atoi(o->value) : -1;
	    if (n < o->minval || n > o->maxval) {
		char s[100];
		sprintf(s, "argument to option \"%s\" / resource \"%s\"",
                    o->option, o->resource);
                usage(s);
            }
            *(int *)(o->where) = n;
        } else if (o->type == Self) {
            *(int *)(o->where) = 1;
        } else /* type == String */
            *(const char **)(o->where) = o->value;
    }
    if (!sound)
	sun_sound(NULL);	/* tell the audio device to shut up */

    if (restoregame &&
       (decks != -1 || slots != -1 || faceup != -1 || facedown != -1))
	  fprintf(stderr, "warning: customization parameters are ignored\n");


    mem_alloc(512);


    if (restoregame)
        load_game(restoregame);
    else
	new_rules(ruleset, decks, slots, faceup, facedown, jokers, flips, turn);

    init_gfx(bkcolor, statusfont, buttonfont);	/* make GCs */
    init_cards(cardset, cround, cround, cbcolor, mem, xpmdir);	/* set size of cards, make pixmaps */
    init_windows(argc, argv, geometry, gapx, gapy, bround, bround,
	bx, by, autolayout); /* size window */
    init_mark(markcolor, linewidth);	/* initialize card marks */
    init_arrow(arrowcolor, arrw, arrh);
    init_exposed_card();
    init_layout();			/* position the piles in a nice way */

    if (restoregame) {
	int replay_to, cheat_count;
	graphic.enable = False;
        cheat_count = game.cheat_count;
        replay_to = game.n_moves;
        newgame(game.seed);
	while (game.n_moves != replay_to)
	    redo_move();
	game.cheat_count = cheat_count;
	for (i = 0; i < game.numpiles; ++i)
	    pile_resize(i);
    } else
	newgame(seed);	/* no save game -- just shuffle */

    graphic.enable = True;
    event_loop();			/* finally: play */
    return 0;
}
