// This may look like C code, but it is really -*- C++ -*-
///////////////////////////////////////////////////////////////////////////
//
//  AMIGA Minesweeper - The event-driven game-loop
//
//  (c) 1992 Hubert Feyrer (c9020@rrzc1.rz.uni-regensburg.de)
//
///////////////////////////////////////////////////////////////////////////

/*
** Diverse "C"-Header
*/
#define class _class
#define template _template
#define IntuitionBase IntuiBase
#define GfxBase GraphBase
extern "C" {
# include <stdio.h>
# include <stdlib.h>
# include <exec/types.h>
# include <exec/exec.h>
# include <exec/Ports.h>
# include <devices/timer.h>
# include <utility/tagitem.h>
# include <intuition/intuition.h>
# include <intuition/intuitionbase.h>
# include <intuition/gadgetclass.h>
# include <graphics/gfxbase.h>
# include <clib/gadtools_protos.h>
# include <clib/intuition_protos.h>
# include <clib/exec_protos.h>
# include <math.h>
}    
#undef IntuitionBase
#undef GfxBase 
#undef class
#undef template

/*
** C++-Header
*/
#include "mine.h"
#include "field.h"

void CancelIO(int idle) { if(!idle){ AbortIO(&treq.tr_node); WaitIO(&treq.tr_node); } }

//*
//* Hauptschleife - das Game an sich und als solches
//*
GameStat play(int idle)
{
    IntuiMessage *imsg;
    int firstgame_over=1;          // Game Over beim ersten Versuch => nochmal!
    int first_touch=1;             // Timer beim ersten Touch starten

    if(idle){
	OnGadget(gogad,win,NULL);
	win->Flags &= ~WFLG_RMBTRAP;
    }else{
	SetWindowTitles(win,WIN_T,-1);
	OffGadget(gogad,win,NULL);
	win->Flags |= WFLG_RMBTRAP;
    }

    GT_RefreshWindow(win,NULL);

    for(;;){
	int isig=1<<win->UserPort->mp_SigBit;         // Intuition-Signal-Bit
	int tsig=1<<tport->mp_SigBit;                 // Timer-Device-Signalbit
	
	int sig=Wait( isig|tsig );
	if(!idle && (sig & tsig)){
	    GetMsg(tport);

	    // Timer sofort wieder starten
	    treq.tr_time.tv_secs=1; 
	    treq.tr_time.tv_micro=0; 
	    SendIO(&treq.tr_node); 

	    playtime++;
	    sprintf(ttimegad,"%04d",playtime);
	    GT_SetGadgetAttrs(timegad,win,NULL,
			      GTTX_Text,ttimegad,
			      TAG_END);
	    RefreshGList(timegad,win,NULL,1);
	}
	if(sig & isig){                               // Message von Intuition
	    while(( imsg=(IntuiMessage *)GT_GetIMsg(win->UserPort) )!=NULL){
		switch(imsg->Class){
		  case IDCMP_CLOSEWINDOW:
		    GT_ReplyIMsg(imsg);
		    if(!first_touch) CancelIO(idle);
		    return GAME_QUIT;
		  case IDCMP_GADGETUP:
		    Gadget *gad = (Gadget *)imsg->IAddress;
		    if(gad==gogad){
			CancelIO(idle);
			return GAME_RESTART;
		    }
		    if(!idle){
			if(first_touch){
			    SendIO(&treq.tr_node);            // Timer starten!
			    first_touch=0;
			}
			//*
			//* Gadget kann direkt bestimmt werden.
			//*
			Field *f=(Field *)gad->UserData;
			
			switch(f->check()){
			  case GAME_WON:
			    CancelIO(idle);
			    return GAME_WON;
			  case GAME_LOST:
			    {
				if(firstgame_over){
				    // Ersatzmine legen
				    int x,y;
				    int i=f->i();
				    int j=f->j();
				    
				    for(;;){
					x=rnd(lenx);
					y=rnd(leny);
					
					if((x==i && y==j) || minefield[x][y]->cnt()==-1)
					  continue;
					else
					  break;
				    }
				    
				    f->cnt(0);
				    minefield[x][y]->cnt(-1);
				    calc_cnt();
				    f->check();
				}else{
				    f->open();
				    CancelIO(idle);
				    return GAME_LOST;
				}
			    }
			    break;
			}
			firstgame_over=0;
		    }
		    break;
		  case IDCMP_MOUSEBUTTONS:
		    if(!idle){
			if(imsg->Code==MENUUP){
			    //*
			    //* Gadget muß aus Maus-Position ermittelt werden.
			    //*
			    int x=imsg->MouseX;
			    int y=imsg->MouseY;
			    if(x>=X0 && y>=Y0){
				int i=(x-X0)/fxs;
				int j=(y-Y0)/fys;
				if(inminefield(i,j)){
				    if(first_touch){
					SendIO(&treq.tr_node);         // Timer starten!
					first_touch=0;
				    }
				    if(minefield[i][j]->mark()==GAME_WON){
					CancelIO(idle);
					return GAME_WON;
				    }
				}
			    }
			}
		    }
		    break;
		}
		GT_ReplyIMsg(imsg);
	    }
	}
    }
    /*NOTREACHED*/
}
