#include "inter.h"
#include "inter.moc"

#include <klocale.h>
#include <kaction.h>
#include <kapplication.h>

#include "factory.h"
#include "field.h"
#include "generic/gsettings.h"


const ActionData Interface::ACTION_DATA[Nb_Actions] = {
    { I18N_NOOP("Move Left"),     "move left",     SLOT(moveLeft()) },
    { I18N_NOOP("Move Right"),    "move right",    SLOT(moveRight()) },
    { I18N_NOOP("Drop Down"),     "drop down",     SLOT(dropDown()) },
    { I18N_NOOP("One Line Down"), "one line down", SLOT(oneLineDown()) },
    { I18N_NOOP("Rotate Left"),   "rotate left",   SLOT(rotateLeft()) },
    { I18N_NOOP("Rotate Right"),  "rotate right",  SLOT(rotateRight()) }
};

const int Interface::KEYCODE_ONE[Nb_Actions] = {
    Key_Left, Key_Right, Key_Down, Key_Shift, Key_Up, Key_Return
};
const int Interface::KEYCODE_TWO[Nb_Actions] = {
    Key_F, Key_G, Key_D, Key_Space, Key_E, Key_Alt
};

Interface::Interface(const MPGameInfo &gi, QWidget *parent)
    : MPSimpleInterface(gi, Nb_Actions, ACTION_DATA, parent)
{
	setDefaultKeycodes(1, 0, KEYCODE_ONE);
	setDefaultKeycodes(2, 0, KEYCODE_TWO);
    setDefaultKeycodes(2, 1, KEYCODE_ONE);
}

MPBoard *Interface::newBoard(uint i)
{
    Field *f = static_cast<Field *>(cfactory->createField(this));
    if ( i==0 ) _firstField = f;
    return f;
}

void Interface::normalGame()
{
    singleHuman();
}

void Interface::arcadeGame()
{
    singleHuman();
    _firstField->setArcade();
}

void Interface::resizeGameOverData(uint size)
{
    uint s = gameOverData.size();
    if ( s>=size ) return;
    KExtHighscores::Score score;
    for (uint i=s; i<size; i++) gameOverData.append(score);
}

void Interface::_init(bool server)
{
	if (server) {
        data.resize(nbPlayers());
        resizeGameOverData(nbPlayers());
    }
}

bool Interface::_readPlayData()
{
	bool end = FALSE;
	for (uint i=0; i<nbPlayers(); i++) {
		readingStream(i) >> data[i];
		if (data[i].end) end = TRUE;
	}
	return end;
}

void Interface::_sendPlayData()
{
	ServerPlayData sd;
	for(uint i=0; i<nbPlayers(); i++) {
		sd.prevHeight = data[prev(i)].height;
		sd.nextHeight = data[next(i)].height;
		sd.gift       = data[prev(i)].gift;
		writingStream(i) << sd;
	}
}

void Interface::_showGameOverData(bool server)
{
    if ( !server || nbPlayers()!=1 )
        KExtHighscores::showMultipleScores(gameOverData, this);
    else if ( !_firstField->isArcade() ) {
        gameOverData[0].setType(KExtHighscores::Won);
        KExtHighscores::submitScore(gameOverData[0], this);
    }
}

uint Interface::prev(uint i) const
{
	if ( i==0 ) return nbPlayers()-1;
	else return i-1;
}

uint Interface::next(uint i) const
{
	if ( i==(nbPlayers()-1) ) return 0;
	else return i+1;
}

// server only
void Interface::_treatInit()
{
	ServerInitData sid;
	sid.seed = kapp->random();
	sid.initLevel = KConfigCollection::configValue("init level").toInt();
	for (uint i=0; i<nbPlayers(); i++) {
        sid.prevName = playerName(prev(i));
        sid.nextName = playerName(next(i));
        sid.name     = playerName(i);
		writingStream(i) << sid;
	}
}

void Interface::_sendGameOverData(QDataStream &s)
{
    s << (Q_UINT32)nbPlayers();

    Q_ASSERT( gameOverData.size()>=nbPlayers() );
	for (uint i=0; i<nbPlayers(); i++) {
        readingStream(i) >> gameOverData[i];
        gameOverData[i].setData("name", playerName(i));
        s << gameOverData[i];
	}
}

// client only
void Interface::_readGameOverData(QDataStream &s)
{
    Q_UINT32 nb;
    s >> nb;
    resizeGameOverData(nb);
    for (uint i=0; i<nb; i++) s >> gameOverData[i];
}
