#ifndef BOARD_H
#define BOARD_H

#include <qcanvas.h>
#include <qtimer.h>
#include <qframe.h>
#include <qpainter.h>
#include "gtetris.h"

class GPieceInfo;
class SequenceArray;
class BlockInfo;
class GiftPool;
class AI;

AI *createAI();

typedef struct {
	uint baseTime, dropDownTime, beforeGlueTime, afterGlueTime;
	uint beforeRemoveTime, afterRemoveTime, afterGiftTime;
} Info;

class Board : public QFrame, public GenericTetris
{
 Q_OBJECT

 public:
    Board(uint blockWidth, uint blockHeight,
		  uint width, uint height, bool graphical, GiftPool *,
		  QWidget *parent, const char *name=0);
	virtual ~Board();

	void setType(bool computer);
	virtual void init(int seed);
	virtual void start();
	void pause();
	void unpause();
	void stop();
	
	QSize sizeHint() const;
	QSizePolicy sizePolicy() const;

	virtual uint gift() = 0;
	bool isGameOver() const { return _end; }
	virtual bool needRemoving() = 0;
	virtual void remove() = 0;

	GiftPool *giftPool() const  { return _giftPool; }
	BlockInfo *next() const { return _next; }
	uint blockWidth() const;
	uint blockHeight() const;
	
	int firstColumnBlock(uint column) const;
	void AIConfigChanged();
	
	void enableAnimations(bool enabled) { _animations = enabled; }

 public slots:
 void pMoveLeft();
    void pMoveRight();
    void pDropDown();
    void pOneLineDown();
    void pRotateLeft();
    void pRotateRight();

 private slots:
    void timeout();

 signals:
    void showNextPieceSignal(bool hide);
	void showPieceConfigSignal(bool hide);
    void updateRemovedSignal(int nbRemoved);
    void updateScoreSignal(int score);
    void updateLevelSignal(int level);

 protected:
	// standard methods
	void newPiece();
	void gameOver();
	void pieceDropped(uint dropHeight);
	virtual bool beforeGlue(bool bump, bool first);
	virtual void gluePiece();
	virtual bool afterGlue(bool /*doAll*/)                { return FALSE; }
	virtual bool beforeRemove(bool /*first*/)             { return FALSE; }
	enum AfterRemoveResult { Done, NeedAfterRemove, NeedRemoving };
	virtual AfterRemoveResult afterRemove(bool /*doAll*/, bool /*first*/)
		                                                  { return Done;  }
	virtual bool afterGift()                              { return FALSE; }
	virtual bool putGift(uint) = 0;

    void updateRemoved(uint addRemoved);
    void updateScore(uint newScore);
    void updateLevel(uint newLlevel);

	uint            loop;
	KRandomSequence randomGarbage;
	Info            info;
	bool            _animations;

 private:
	void checkGift();
	void _afterGift();
	void _beforeGlue(bool first);
	void _afterGlue();
	void _beforeRemove(bool first);
	void _afterRemove(bool first);
	void startTimer();
	void showNextPiece(bool show)   { emit showNextPieceSignal(!show); }
	void showPieceConfig(bool show) { emit showPieceConfigSignal(!show); }
	void showBoard(bool show);
	void showCanvas(QCanvas *c, bool show);

	enum BoardState { Normal, DropDown, BeforeGlue, AfterGlue, BeforeRemove,
					  AfterRemove, AfterGift };
	BoardState        state;
	QTimer            timer;
	uint              _dropHeight;
	bool              _end;
	GiftPool         *_giftPool;
	AI               *aiEngine;
	SequenceArray    *sequences;
	BlockInfo        *main, *_next;
	QCanvasView      *view;
};

#endif
