/*

    $Id: kmahjongg.h,v 1.14 1999/12/13 14:19:47 waba Exp $

    kmahjongg, the classic mahjongg game for KDE project

    Requires the Qt widget libraries, available at no cost at
    http://www.troll.no 

    Copyright (C) 1997 Mathias Mueller   <in5y158@public.uni-hamburg.de>

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
  
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
  
    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.    

*/

#ifndef _KMAHJONGG_H
#define _KMAHJONGG_H

class KMenuBar;
class QLabel;

#include <qfiledlg.h>

#include <kapp.h>
#include <kmessagebox.h> 
#include <krandomsequence.h>

#include <ktmainwindow.h>
#include "KmTypes.h"
#include "Tileset.h"
#include "Background.h"
#include "Preferences.h"
#include "PrefsDlg.h"
#include "GameTimer.h" 
#include "GameNum.h"
#include "BoardLayout.h"
#include "Preview.h"
#include "HighScore.h"
#include "Editor.h"


//----------------------------------------------------------
// DEFINES
//----------------------------------------------------------

// maximum of tiles on gameboard


static const char *gameMagic = "kmahjongg-game-v1.0";


typedef struct gamedata {
    int      allow_undo;
    int      allow_redo;
    UCHAR    Board[BoardLayout::depth][BoardLayout::height][BoardLayout::width]; 
    USHORT   TileNum;          
    USHORT   MaxTileNum;       
    UCHAR    Mask[BoardLayout::depth][BoardLayout::height][BoardLayout::width];
    UCHAR    hilighted[BoardLayout::depth][BoardLayout::height][BoardLayout::width];
    POSITION MoveList[BoardLayout::maxTiles];
    void putTile( short e, short y, short x, UCHAR f )
    {
	    

        Board[e][y][x] = Board[e][y+1][x] = 
		   Board[e][y+1][x+1] = Board[e][y][x+1] = f;
    }
    void putTile( POSITION& pos )
    {
        putTile( pos.e, pos.y, pos.x, pos.f );
    }


    bool tilePresent(int z, int y, int x) {
	return(Board[z][y][x]!=0 && Mask[z][y][x] == '1');
    }

    bool partTile(int z, int y, int x) {
	return (Board[z][y][x] != 0);
    }

    int shadowHeight(int z, int y, int x) {


    if ((z>=BoardLayout::depth||y>=BoardLayout::height||x>=BoardLayout::width)) 
	return 0;
	

	if ((y < 0) || (x < 0))
		return 0;
	
	int h=0;
	for (int e=z; e<BoardLayout::depth; e++) {
		if (Board[e][y][x] && Mask[e][y][x]) {
			
			
			h++;
		} else {
			return h;	
		}
			
	}
	return h;
    }
    
    
} GAMEDATA;






/**
    ...

    @author Mathias Mueller
*/
class BoardWidget : public QWidget
{
    Q_OBJECT

    public:
        BoardWidget( QWidget* parent );

        void calculateNewGame(int num = -1 );
        void helpMove();
        int  undoMove();
	void redoMove(void);
        void startDemoMode();
        void stopDemoMode();

	void pause();

	void shuffle(void);
        void animateMoveList();
        void setShowMatch( bool );
	void tileSizeChanged(void);
	long getGameNum(void) {return gameGenerationNum;};
	QString &getBoardName(void){return theBoardLayout.getFilename();}; 
	QString &getLayoutName(void) {return theBoardLayout.getFilename();};

	
    public slots:
        void helpMoveTimeout();
        void demoMoveTimeout();
        void matchAnimationTimeout();
	void setDisplayedWidth();
        bool loadTileset    ( const char* );
        bool loadBoardLayout( const char* );
        bool loadBoard      ( );
        void updateScaleMode (void);
        void drawBoard(bool deferUpdate = true);
        bool loadBackground ( const char*, bool bShowError = true );
    signals:
        void statusTextChanged ( const char*, long );
        void message           ( const char* );
        void tileNumberChanged ( int iMaximum, int iCurrent );
        void demoModeChanged   ( bool bActive );

	void gameCalculated(void);
	
		void gameOver(unsigned short removed, unsigned short cheats);
    protected:
	void getFileOrDefault(QString filename, QString type, QString &res);		
	void shadowArea(int z, int y, int x, int sx, int sy, int rx, int ry, QPixmap *src);
	void shadowTopLeft(int depth, int sx, int sy, int rx, int ry,QPixmap *src, bool flag);	
	void shadowBotRight(int depth, int sx, int sy, int rx, int ry,QPixmap *src, bool flag);	
        void paintEvent      ( QPaintEvent* );
        void mousePressEvent ( QMouseEvent* );

        void setStatusText ( const char* );
        void showMessage   ( const char* );
        void cancelUserSelectedTiles();
        void drawTileNumber();

        void hilightTile ( POSITION&, bool on=true, bool refresh=true );
        void putTile     ( POSITION& , bool refresh = true);
        void removeTile  ( POSITION& , bool refresh = true);
	void setRemovedTilePair(POSITION &a, POSITION &b);
	void clearRemovedTilePair(POSITION &a, POSITION &b);
        void transformPointToPosition( const QPoint&, POSITION& );

        bool isMatchingTile( POSITION&, POSITION& );
        bool generateStartPosition2();
        bool findMove( POSITION&, POSITION& );
        short findAllMatchingTiles( POSITION& );
        void stopMatchAnimation();
	void stackTiles(unsigned char t, unsigned short h, unsigned short x,unsigned  short y);
	void initialiseRemovedTiles(void); 

	int requiredWidth(void);
	int requiredHeight(void);

	void calcShadow(int e, int y, int x, int &left, int &right, int &corn);


	// new bits for game generation
	void randomiseFaces(void);
	int tilesAllocated;
	int tilesUsed;
	void getFaces(POSITION &a, POSITION &b);
	UCHAR tilePair[144];
	
	KRandomSequence random;
	
	Tileset  theTiles;         
	Background theBackground;
	
	
	
	BoardLayout theBoardLayout;


        int iPosCount;             // count of valid positions in PosTable
        POSITION PosTable[BoardLayout::maxTiles];   // Table of all possible positions
        POSITION MouseClickPos1, MouseClickPos2;
        POSITION TimerPos1, TimerPos2;

        enum STATES { Stop, Demo, Help, Animation, Match } TimerState;
        int iTimerStep;

        short matchCount;
        bool  showMatch;

	
	
	
	// offscreen draw area.
	QPixmap backBuffer;		// pixmap to render to
	
	

	bool    updateBackBuffer;	// does board need redrawing. Not if it is just a repaint

	bool gamePaused;

	// storage for hiscore claculation
	unsigned short cheatsUsed;

	// seed for the random number generator used for this game
	long  gameGenerationNum;
	
	// storage to keep track of removed tiles
	unsigned char removedCharacter[9];
	unsigned char removedBamboo[9];
	unsigned char removedRod[9];
	unsigned char removedDragon[3];
	unsigned char removedWind[9];
	unsigned char removedFlower[4];
	unsigned char removedSeason[4];
	
public:
        GAMEDATA Game;         
};





/**
    ...
    @author Mathias 
*/
class KMahjonggWidget : public KTMainWindow
{
    Q_OBJECT

    public:
        KMahjonggWidget();
        ~KMahjonggWidget();



    public slots:
        void menuCallback( int );
        void startNewGame( int num = -1 );
        void showStatusText ( const char* , long);
        void showMessage    ( const char* );
        void showTileNumber( int iMaximum, int iCurrent );
        void demoModeChanged( bool bActive );
		void gameOver( unsigned short removed, unsigned short cheats);
 	void statusBarMode(int onOff); 
	void backgroundMode();
	void loadBoardLayout(const char *);
	void setDisplayedWidth();
	void newGame(void);
	void timerReset(void);
	
	void tileSizeChanged(void);

    protected:
        void closeEvent ( QCloseEvent* );

        void setupStatusBar();
        void setupMenuBar();
        void setupToolBar();
        void updateStatusbar( bool );
	void enableItem(int item, bool state);
	void loadGame(void);
	void saveGame(void);

    private:
	// number of seconds since the start of the game
	unsigned long gameElapsedTime;
        BoardWidget* bw;

	QLabel *gameNumLabel;
	QLabel *tilesLeftLabel;
	QLabel *statusLabel;
	
	GameNum	     *gameNum;
	GameTimer    *gameTimer;
	HighScore    *theHighScores;
        KStatusBar*  pStatusBar;
	KToolBar     *toolBar;
        KMenuBar*    pMenuBar;
	PrefsDlg     prefsDlg;
	Preview      previewLoad;
	Editor	     boardEditor;

        bool         bShowStatusbar;
        bool         bShowMatchingTiles;
        bool         bDemoModeActive;
};

			    


#endif





