/*
 * fcwind.c - The freecell window
 */

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

#include "err.h"
#include "fc.h"

#include "area.h"
#include "card.h"
#include "cslot.h"
#include "cslota.h"
#include "cstack.h"
#include "cstacka.h"
#include "cpile.h"
#include "cpilea.h"
#include "game.h"

/* ---------- Function declarations ---------- */
void fcwind_open(struct wind *);
void fcwind_term(struct wind *);
void fcwind_mouse(struct wind *, XButtonEvent *);
void fcwind_draw(struct wind *, Region);
void fcwind_resize(struct wind *, XConfigureEvent *);
void fcwind_key(struct wind *, XKeyEvent *);
void fcwind_activate(struct wind *, XMapEvent *);
void fcwind_deactivate(struct wind *, XUnmapEvent *);

static void make_floater(struct wind *, XButtonEvent *);
static void clear_floater(struct wind *, XButtonEvent *);

/* ---------------------------------------------------------------------- */
struct wind_ops fcwind_ops = {
     fcwind_open,
     fcwind_term,
     fcwind_mouse,
     fcwind_draw,
     fcwind_resize,
     fcwind_key,
     fcwind_activate,
     fcwind_deactivate
};

/* ---------------------------------------------------------------------- */
void 
fcwind_open(struct wind *windp)
{
     struct fcw *fcp = &windp->onion.fcw;
     struct aop ao;
     int i;

     windp->ops = &fcwind_ops;

     /* Make the game */
     fcp->gp = game_create();
     game_reinit(fcp->gp, 0);

     /* Create some areas */
     ao.x = CARD_SPACE;
     ao.y = CARD_HEIGHT + CARD_SPACE * 2;
     ao.width = CARD_WIDTH;
     ao.height = 500;
     ao.owner = windp;
     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  fcp->csapp[i] = 
	       cstacka_create(game_getstack(fcp->gp, i), &ao); 
	  ao.x += CARD_WIDTH + CARD_SPACE;
     }

     ao.x = CARD_SPACE + 4 * (CARD_WIDTH + CARD_SPACE);
     ao.y = CARD_SPACE;
     ao.width = CARD_WIDTH;
     ao.height = CARD_HEIGHT;
     ao.owner = windp;
     for (i = 0; i < GAME_NUM_SUITS; i++) {
	  fcp->clapp[i] = 
	       cpilea_create(game_getsuit(fcp->gp, i), &ao);
	  ao.x += CARD_WIDTH + CARD_SPACE;
     }
     
     ao.x = CARD_SPACE;
     ao.y = CARD_SPACE;
     ao.width = CARD_WIDTH;
     ao.height = CARD_HEIGHT;
     ao.owner = windp;
     for (i = 0; i < GAME_NUM_CELLS; i++) {
	  fcp->cdapp[i] =
	     cslota_create(game_getcell(fcp->gp, i), &ao);
	  ao.x += CARD_WIDTH + CARD_SPACE;
     }
}

/* ---------------------------------------------------------------------- */
void 
fcwind_term(struct wind *windp)
{
     struct fcw *fcp = &windp->onion.fcw;
     int i;
     
     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  area_destroy(fcp->csapp[i]);
     }
     for (i = 0; i < GAME_NUM_SUITS; i++) {
	  area_destroy(fcp->clapp[i]);
     }
     for (i = 0; i < GAME_NUM_CELLS; i++) {
	  area_destroy(fcp->cdapp[i]);
     }
}

/* ---------------------------------------------------------------------- */
void 
fcwind_mouse(struct wind *windp, XButtonEvent *ev)
{
     struct fcw *fcp = &windp->onion.fcw;
     int i;
     
     if (ev->type == ButtonRelease && fcp->floaterp == NULL) return;

     /* If we have a floater, then ignore all other events. */
     if (fcp->floaterp && ev->button != 3) return;
	  
     if (ev->button == 3) {
	  if (ev->type == ButtonRelease) {
	       clear_floater(windp, ev);
	  }
	  else {
	       make_floater(windp, ev);
	  }
	  return;
     }

     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  if (area_containspoint(fcp->csapp[i], ev->x, ev->y)) {
	       if (area_isdoubleclick(fcp->csapp[i])) {
		    game_dclickitem(fcp->gp, game_itemcode(GAME_STACKS, i));
	       }
	       else {
		    game_clickitem(fcp->gp, game_itemcode(GAME_STACKS, i));
	       }
	       return;
	  }
     }
     for (i = 0; i < GAME_NUM_SUITS; i++) {
	  if (area_containspoint(fcp->clapp[i], ev->x, ev->y)) {
	       if (area_isdoubleclick(fcp->csapp[i])) {
		    game_dclickitem(fcp->gp, game_itemcode(GAME_SUITS, i));
	       }
	       else {
		    game_clickitem(fcp->gp, game_itemcode(GAME_SUITS, i));
	       }
	       return;
	  }
     }
     for (i = 0; i < GAME_NUM_CELLS; i++) {
	  if (area_containspoint(fcp->cdapp[i], ev->x, ev->y)) {
	       if (area_isdoubleclick(fcp->csapp[i])) {
		    game_dclickitem(fcp->gp, game_itemcode(GAME_CELLS, i));
	       }
	       else {
		    game_clickitem(fcp->gp, game_itemcode(GAME_CELLS, i));
	       }
	       return;
	  }
     }
}

/* ---------------------------------------------------------------------- */
void 
fcwind_draw(struct wind *windp, Region rgn)
{
     struct fcw *fcp = &windp->onion.fcw;
     int i;

     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  if (area_inrgn(fcp->csapp[i], rgn)) {
	       area_draw(fcp->csapp[i], rgn);
	  }
     }
     for (i = 0; i < GAME_NUM_SUITS; i++) {
	  if (area_inrgn(fcp->clapp[i], rgn)) {
	       area_draw(fcp->clapp[i], rgn);
	  }
     }
     for (i = 0; i < GAME_NUM_CELLS; i++) {
	  if (area_inrgn(fcp->cdapp[i], rgn)) {
	       area_draw(fcp->cdapp[i], rgn);
	  }
     }
     if (fcp->floaterp && area_inrgn(fcp->floaterp, rgn)) {
	  area_draw(fcp->floaterp, rgn);
     }
}

/* ---------------------------------------------------------------------- */
void 
fcwind_resize(struct wind *windp, XConfigureEvent *ev)
{
     
}

/* ---------------------------------------------------------------------- */
void 
fcwind_key(struct wind *windp, XKeyEvent *ev)
{
     struct fcw *fcp = &windp->onion.fcw;
     KeySym ks;

     ks = XKeycodeToKeysym(dpy, ev->keycode, 0);
     switch(ks) {
     case XK_Q:
     case XK_q:
	  done = 1;
	  break;
     case XK_s:
     {
	  static synch = FALSE;

	  synch = !synch;
	  XSynchronize(dpy, synch);
     }
	  break;
     case XK_r:
	  {
	       XRectangle trect;

	       round_cards = !round_cards;
	       trect.x = trect.y = 0;
	       trect.height = trect.width = 65535;
	       clear_rect(dpy, windp, &trect, TRUE);
	       break;
	  }
     case XK_d:
	  game_reinit(fcp->gp, 0);
/*	  fcwind_resetareas(fcwind);*/
	  break;	  
     }
}

/* ---------------------------------------------------------------------- */
void 
fcwind_activate(struct wind *windp, XMapEvent *ev)
{

}

/* ---------------------------------------------------------------------- */
void 
fcwind_deactivate(struct wind *windp, XUnmapEvent *ev)
{

}

/* ---------------------------------------------------------------------- */
void
make_floater(struct wind *windp, XButtonEvent *ev)
{
     struct fcw *fcp = &windp->onion.fcw;
     struct area *csap = NULL;
     XRectangle trect;
     struct cslot *ctp;
     struct cstack *csp;
     struct card *cdp, *cdp_copy;
     struct aop aop;
     int cardnum, i;

     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  if (area_containspoint(fcp->csapp[i], ev->x, ev->y)) {
	       csap = fcp->csapp[i];
	       break;
	  }
     }
     /* Not on a stack */
     if (csap == NULL) return;

     cardnum = cstacka_findcard(csap, ev->x, ev->y);
     if (cardnum < 0) return;

     cstacka_getcardrect(csap, cardnum, FALSE, &trect);

     ctp = cslot_create();
     csp = cstacka_getcstack(csap);
     cdp = cstack_getcard(csp, cardnum);
     cdp_copy = card_copy(cdp);
     cslot_addcard(ctp, cdp_copy);

     aop.x = trect.x;
     aop.y = trect.y;
     aop.width = trect.width;
     aop.height = trect.height;
     aop.owner = windp;
     fcp->floaterp = cslota_create(ctp, &aop);
     
     area_clear(fcp->floaterp);
}

/* ---------------------------------------------------------------------- */
void
clear_floater(struct wind *windp, XButtonEvent *ev)
{
     struct fcw *fcp = &windp->onion.fcw;

     area_clear(fcp->floaterp);
     area_destroy(fcp->floaterp);
     fcp->floaterp = NULL;
}

/* ---------------------------------------------------------------------- */
#ifdef SCROTUM
void
fcwind_resetareas(struct wind *windp)
{
     struct fcw *fcp = &windp->onion.fcw;
     int i;

     for (i = 0; i < GAME_NUM_CELLS; i++) {
	  cslota_resetcslot(fcp->cdapp[i], game_getcell(fcp->gp, i));
     }
     for (i = 0; i < GAME_NUM_STACKS; i++) {
	  cstacka_resetcstack(fcp->csapp[i], game_getstack(fcp->gp, i));
     }
     for (i = 0; i < GAME_NUM_SUITS; i++) {
	  cpilea_resetcpile(fcp->clapp[i], game_getsuit(fcp->gp, i));
     }
}
#endif
