#include "field.h"
#include "field.moc"

#include <qobjectlist.h>
#include <qwhatsthis.h>
#include <klocale.h>
#include "defines.h"
#include "misc_ui.h"
#include "types.h"

Field::Field(QWidget *parent, const char *name)
: MPSimpleBoard(parent, name)
{
	installEventFilter(topLevelWidget());

	board = createBoard(this);

	QGridLayout *top;
	QVBoxLayout *vbl;
	QLabel *lab;

// top layout (grid)	
	top = new QGridLayout(this, 3, 5, BORDER);

// column 1
    // previous player name
	prevName = new QLabel(" ", this);
	prevName->setAlignment(AlignRight);
	QWhatsThis::add(prevName, i18n("Previous player's name"));
	top->addWidget(prevName, 0, 0);

	// LCDs
	vbl = new QVBoxLayout(SEPARATOR);
	top->addLayout(vbl, 1, 0);
	vbl->addStretch(1);
	
      // score LCD
	lab = new QLabel(i18n("Score"), this);
	lab->setAlignment(AlignCenter);
	vbl->addWidget(lab, 0);
	showScore = new QLCDNumber(6, this);
	showScore->setSegmentStyle(QLCDNumber::Flat);
	showScore->setFixedHeight(LCD_HEIGHT);
	vbl->addWidget(showScore);
	vbl->addStretch(1);
	  // removed LCD
	lab = new QLabel(i18n("Removed"), this);
	lab->setAlignment(AlignCenter);
	vbl->addWidget(lab, 0);
	showLines = new QLCDNumber(4, this);
	showLines->setSegmentStyle(QLCDNumber::Flat);
	showLines->setFixedHeight(LCD_HEIGHT);
	vbl->addWidget(showLines);
	vbl->addStretch(1);
	  // level LCD
	lab = new QLabel(i18n("Level"), this);
	lab->setAlignment(AlignCenter);
	vbl->addWidget(lab, 0);
	showLevel = new QLCDNumber(2, this);
	showLevel->setSegmentStyle(QLCDNumber::Flat);
	showLevel->setFixedHeight(LCD_HEIGHT);
	vbl->addWidget(showLevel);
	vbl->addStretch(1);

// column 2
    // gift received shower
	giftReceived = new GiftShower(GIFT_SHOWER_TIMEOUT, this);
	QWhatsThis::add(giftReceived, i18n("Lights when a \"gift\" is received "
									   "from previous player"));
	top->addWidget(giftReceived, 0, 1);

    // previous player height
	prevHeight = new KProgress(0, ((const Board *)board)->matrix().height(),
							   0, KProgress::Vertical, this);
	prevHeight->setFixedWidth(PROGRESS_WIDTH);
	prevHeight->setBackgroundColor(lightGray);
	prevHeight->setTextEnabled(FALSE);
	prevHeight->setBarColor(blue);
	QWhatsThis::add(prevHeight, i18n("Previous player's height"));
	top->addWidget(prevHeight, 1, 1);

// column 3
	// pending gift shower
	top->addWidget(board->giftPool(), 0, 2);

    // board
	board->setFixedSize( board->sizeHint() );
	connect(board,     SIGNAL(updateScoreSignal(int)),
			showScore, SLOT(display(int)));
	connect(board,     SIGNAL(updateRemovedSignal(int)),
			showLines, SLOT(display(int)));
	connect(board,     SIGNAL(updateLevelSignal(int)),
			showLevel, SLOT(display(int)));
	top->addWidget(board, 1, 2);
	
    // shadow piece
	shadow = new Shadow(board, board->frameWidth(), this);
	QWhatsThis::add(shadow, i18n("Shadow of the current piece"));
	connect(board,  SIGNAL(showPieceConfigSignal(bool)),
			shadow, SLOT(redraw(bool)));
	top->addWidget(shadow, 2, 2);

// column 4
	// gift sent shower
	giftSent = new GiftShower(GIFT_SHOWER_TIMEOUT, this);
	QWhatsThis::add(giftSent, i18n("Lights when you send a \"gift\" to the "
								   "next player"));
	top->addWidget(giftSent, 0, 3);

    // next player height
	nextHeight = new KProgress(0, ((const Board *)board)->matrix().height(),
							   0, KProgress::Vertical, this);
	nextHeight->setFixedWidth(PROGRESS_WIDTH);
	nextHeight->setBackgroundColor(lightGray);
	nextHeight->setTextEnabled(FALSE);
	nextHeight->setBarColor(blue);
	QWhatsThis::add(nextHeight, i18n("Next player's height"));
	top->addWidget(nextHeight, 1, 3);

// column 5	
    // next player name
	nextName = new QLabel(" ", this);
	QWhatsThis::add(nextName, i18n("Next player's name"));
	top->addWidget(nextName, 0, 4);
	
    // next piece shower
	vbl = new QVBoxLayout(SEPARATOR);
	top->addLayout(vbl, 1, 4);
	vbl->addStretch(1);

	labShowNext = new QLabel(i18n("Next tile"), this);
	labShowNext->setAlignment(AlignCenter);
	vbl->addWidget(labShowNext, 0);
	showNext = new ShowNextPiece(board->next(), this);
	vbl->addWidget(showNext, 0);
	vbl->addStretch(4);

// install event handler for all child widgets
	QObjectList *list = queryList("QWidget");
	QObjectListIt it(*list);
	QObject *obj;
	while ( (obj=it.current()) ) {
		((QWidget *)obj)->installEventFilter(topLevelWidget());
		++it;
	}

// board layout
	QVBoxLayout *btop = new QVBoxLayout(board);
	btop->addStretch(3);

	msg = new QLabel(board);
	msg->setAlignment(AlignCenter);
	msg->setFrameStyle( QFrame::Panel | QFrame::Sunken );
	msg->installEventFilter(topLevelWidget());
	btop->addWidget(msg, 0, AlignCenter);
	msg->hide();
	btop->addStretch(1);

	// #### the string is dummy : it seems necessary to have the "good" size !?
	pb = new QPushButton(" ", board);
	pb->installEventFilter(topLevelWidget());
	btop->addWidget(pb, 0, AlignCenter);
    pb->hide();
	btop->addStretch(3);
}

QSizePolicy Field::sizePolicy() const
{
	return QSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
}

void Field::showOpponents(bool show)
{
	if (show) {
		prevHeight->show();
		nextHeight->show();
		prevName->show();
		nextName->show();
		giftReceived->show();
		giftSent->show();
		board->giftPool()->show();
	} else {
		prevHeight->hide();
		nextHeight->hide();
		prevName->hide();
		nextName->hide();
		giftReceived->hide();
		giftSent->hide();
		board->giftPool()->hide();
	}
}

void Field::enablePreference(int type, bool enabled)
{
	switch ((PreferenceType)type) {
	case ShowNext:
		if (enabled) {
			showNext->show();
			labShowNext->show();
		} else {
			showNext->hide();
			labShowNext->hide();
		}
		break;
	case ShowShadow:
		if (enabled) shadow->show();
		else shadow->hide();
		break;
	case Animations:
		board->enableAnimations(enabled);
		break;
	default:
		break;
	}
}

void Field::AIConfigChanged()
{
	board->AIConfigChanged();
}

void Field::_init(bool AI, bool multiplayers, bool server, bool first,
				  const QString &name)
{
	QString msg;
	msg = (AI ? i18n("%1\n(AI player)").arg(name)
		   : (multiplayers ? i18n("%1\n(Human player)").arg(name)
			  : QString::null));
	if ( first && !server ) msg = msg + i18n("\nWaiting for server start");
	button = (first && server);
	midButton((button ? i18n("Press to start") : QString::null), msg);
	showOpponents(multiplayers);
	board->setType(AI);
}

void Field::midButton(const QString &pt, const QString &mt, bool start)
{
	if ( !mt.isNull() ) {
		msg->setText(mt);	
		msg->show();
	} else msg->hide();

	if ( !pt.isNull() ) {
		pb->setText(pt);
		pb->show();
		pb->setFocus();
		if (start) connect(pb, SIGNAL(clicked()), parent(), SLOT(start()));
		else connect(pb, SIGNAL(clicked()), parent(), SLOT(pause()));
	} else {
		pb->hide();
		pb->clearFocus();
		pb->disconnect(SIGNAL(clicked()));
	}
}

void Field::_initFlag(QDataStream &s)
{
	ServerInitData sid;
	s >> sid;
	prevName->setText(sid.prevName);
	nextName->setText(sid.nextName);
	board->init(sid.seed);
	
	midButton();
	board->start();
	shadow->reveal(TRUE);
}

void Field::_playFlag(QDataStream &s)
{
	ServerPlayData sd;
	s >> sd;
	prevHeight->setValue(sd.prevHeight);
	nextHeight->setValue(sd.nextHeight);
	if (sd.gift) {
		giftReceived->set();
		board->giftPool()->put(sd.gift);
	}
}

void Field::_pauseFlag(bool pause)
{
	if (pause) {
		board->pause();
		midButton((button ? i18n("Press to resume") : QString::null),
				  i18n("Game paused"), FALSE);
	} else {
		midButton();
		board->unpause();
	}
	shadow->reveal(!pause);
}

void Field::_stopFlag(bool gameover)
{
	board->stop();
	if (gameover) midButton((button ? i18n("Press to start") : QString::null),
							i18n("Game over"));
}

void Field::_dataOut(QDataStream &s)
{
	ClientPlayData cd;
	cd.gift   = board->gift();
	cd.height = board->firstClearLine();
	cd.end    = board->isGameOver();
	s << cd;
	if (cd.gift) giftSent->set();
}

void Field::_gameOverDataOut(QDataStream &s)
{
	GameOverItem cd;
	cd.score = board->score();
	cd.level = board->level();
	cd.name  = "1"; // we let the server fill the name ...
	s << cd;
}

void Field::_initDataOut(QDataStream &)
{
	// #### TODO (?)
}
