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

#include <qwhatsthis.h>
#include <qlabel.h>
#include <qlayout.h>

#include <klocale.h>
#include <kprogress.h>
#include <kgameprogress.h>
#include <kcanvasrootpixmap.h>

#include "generic/gmisc_ui.h"
#include "generic/gsettings.h"

#include "factory.h"
#include "highscores.h"
#include "misc_ui.h"
#include "board.h"


Field::Field(QWidget *parent)
: MPSimpleBoard(parent), BaseField(this)
{
// 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);

    // score LCD
    scoreList = new KGameLCDList(this);
    showScore = new KGameLCD(6, scoreList);
    scoreList->append(showScore);
    showTime = new KGameLCDClock(scoreList);
    scoreList->append(showTime);
    lcds->addWidget(scoreList, 1, 0);
    lcds->setRowStretch(2, 1);

    // removed LCD
    removedList =
        new KGameLCDList(i18n(bfactory->mainData.removedLabel), this);
    lcds->addWidget(removedList, 3, 0);
    lcds->setRowStretch(4, 1);

	// level LCD + progress
    showLevel = new KGameLCDList(this);
    showLevel->append(new KGameLCD(2, showLevel));
    showLevel->lcd(0)->display(1);
    lcds->addWidget(showLevel, 5, 0);
    toLevel = new KProgress(this);
    toLevel->setTextEnabled(true);
    toLevel->setFormat("%v/%m");
    QWhatsThis::add(toLevel, i18n("Display the progress to complete the "
                                  "current level or stage."));
    toLevel->setPercentageVisible(false);
    lcds->addWidget(toLevel, 6, 0);
    lcds->setRowStretch(7, 1);

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

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

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

    // shadow piece
	shadow = new Shadow(board, this);
	QWhatsThis::add(shadow, i18n("Shadow of the current piece"));
	top->addWidget(shadow, 2, 2);

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

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

// 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
	QVBoxLayout *vbl = new QVBoxLayout(10);
	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, this);
    _snRootPixmap = new KCanvasRootPixmap(showNext);
    _snRootPixmap->start();
	vbl->addWidget(showNext, 0);
	vbl->addStretch(4);

    connect(board, SIGNAL(scoreUpdated(int)), SLOT(scoreUpdated(int)));
    connect(board, SIGNAL(levelUpdated(int)), SLOT(levelUpdated(int)));
    connect(board, SIGNAL(removedUpdated(int)), SLOT(removedUpdated(int)));

    initVariableGUI();
}

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

void Field::levelUpdated(int level)
{
    showLevel->lcd(0)->display(level);
    if ( level>1 ) static_cast<KGameLCD *>(showLevel->lcd(0))->highlight();
}

void Field::removedUpdated(int removed)
{
    uint nb = cfactory->cbi.nbRemovedToLevel;
    toLevel->setProgress(isArcade() ? board->arcadeDone() : removed % nb);
}

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

void Field::settingsChanged()
{
    BaseField::settingsChanged();
    QColor color = KConfigCollection::configValue("fade color").toColor();
    double s = KConfigCollection::configValue("fade intensity").toDouble();
    _snRootPixmap->setFadeEffect(s, color);
    showNext->canvas()->setBackgroundColor(color);
    bool b = KConfigCollection::configValue("show next piece").toBool();
    showNextPiece(b);
    b = KConfigCollection::configValue("show piece shadow").toBool();
    showShadow(b);
}

void Field::showNextPiece(bool show)
{
   if (show) {
       showNext->show();
       labShowNext->show();
   } else {
       showNext->hide();
       labShowNext->hide();
   }
}

void Field::showShadow(bool show)
{
   if (show) shadow->show();
   else shadow->hide();
}

void Field::_init(bool AI, bool multiplayer, bool server, bool first,
                  const QString &name)
{
    BaseField::init(AI, multiplayer, server, first, name);
	showOpponents(multiplayer);
	static_cast<Board *>(board)->setType(AI);
}

void Field::_initFlag(QDataStream &s)
{
	ServerInitData sid;
	s >> sid;
    GTInitData data;
    data.seed = sid.seed;
    data.initLevel = sid.initLevel;
    prevName->setText(sid.prevName);
	nextName->setText(sid.nextName);

    shadow->setDisplay(true);
    toLevel->setValue(0);
    showTime->reset();
    showTime->start();

    BaseField::start(data);
    initVariableGUI();
}

void Field::initVariableGUI()
{
    if ( board->isArcade() ) {
        scoreList->title()->setText(i18n("Elapsed time"));
        showScore->hide();
        showTime->show();
        QWhatsThis::add(scoreList, i18n("Display the elapsed time"));
        showLevel->title()->setText(i18n("Stage"));
        showLevel->lcd(0)->display((int)board->arcadeStage()+1);
        toLevel->setRange(0, board->arcadeTodo());
    } else {
        scoreList->title()->setText(i18n("Score"));
        showScore->show();
        showTime->hide();
        QWhatsThis::add(scoreList,
                        i18n("<qt>Display the current score.<br/>"
                             "It turns <font color=\"blue\">blue</font>"
                             " if it is a highscore "
                             "and <font color=\"red\">red</font> "
                             "if it is the best local score.</qt>"));
        showLevel->title()->setText(i18n("Level"));
        toLevel->setRange(0, cfactory->cbi.nbRemovedToLevel);
    }
}

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

void Field::_pauseFlag(bool p)
{
    pause(p);
    shadow->setDisplay(!p);
    if (p) showTime->stop();
    else showTime->start();
}

void Field::_stopFlag(bool gameover)
{
    BaseField::stop(gameover);
    showTime->stop();
}

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

KExtHighscores::Score Field::currentScore() const
{
    KExtHighscores::Score score;
    score.setType(_cpd.end ? KExtHighscores::Lost : KExtHighscores::Won);
    score.setData("score", board->score());
    score.setData("level", board->level());
    score.setData("removed", board->nbRemoved());
    return score;
}

void Field::_gameOverDataOut(QDataStream &s)
{
	s << currentScore();
}

void Field::moveLeft() { static_cast<Board *>(board)->pMoveLeft(); }
void Field::moveRight() { static_cast<Board *>(board)->pMoveRight(); }
void Field::dropDown() { static_cast<Board *>(board)->pDropDown(); }
void Field::oneLineDown() { static_cast<Board *>(board)->pOneLineDown(); }
void Field::rotateLeft() { static_cast<Board *>(board)->pRotateLeft(); }
void Field::rotateRight() { static_cast<Board *>(board)->pRotateRight(); }
