/*
 * mainwindow.cpp - plugin
 * Copyright (C) 2010  Evgeny Khryukin
 *
 * 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 library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 *
 */

#include "mainwindow.h"

#include <QFileDialog>
#include <QTextCodec>
#include <QTextStream>

using namespace Chess;

SelectFigure::SelectFigure(const QString& player, QWidget *parent)
    : QWidget(parent)
{
    setAttribute(Qt::WA_DeleteOnClose);
    setWindowModality(Qt::WindowModal);
    setFixedSize(62,62);
    setStyleSheet("QPushButton { background-color: #e9edff;}"
              "QPushButton:hover { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e9edff, stop: 1 black)}");
    QGridLayout *layout = new QGridLayout(this);
    tb_queen = new QPushButton(this);
    tb_castle = new QPushButton(this);
    tb_knight = new QPushButton(this);
    tb_bishop = new QPushButton(this);
    tb_queen->setFixedSize(25,25);
    tb_queen->setObjectName("queen");
    tb_castle->setFixedSize(25,25);
    tb_castle->setObjectName("rook");
    tb_knight->setFixedSize(25,25);
    tb_knight->setObjectName("knight");
    tb_bishop->setFixedSize(25,25);
    tb_bishop->setObjectName("bishop");
    if(player == "white") {
                tb_queen->setIcon(QIcon(QPixmap(":/chessplugin/figures/white_queen.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_castle->setIcon(QIcon(QPixmap(":/chessplugin/figures/white_castle.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_knight->setIcon(QIcon(QPixmap(":/chessplugin/figures/white_knight.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_bishop->setIcon(QIcon(QPixmap(":/chessplugin/figures/white_bishop.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
    }
    else {
                tb_queen->setIcon(QIcon(QPixmap(":/chessplugin/figures/black_queen.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_castle->setIcon(QIcon(QPixmap(":/chessplugin/figures/black_castle.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_knight->setIcon(QIcon(QPixmap(":/chessplugin/figures/black_knight.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
                tb_bishop->setIcon(QIcon(QPixmap(":/chessplugin/figures/black_bishop.png").scaled(22,22, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
    }

    layout->addWidget(tb_queen,0,0);
    layout->addWidget(tb_castle,1,0);
    layout->addWidget(tb_knight,0,1);
    layout->addWidget(tb_bishop,1,1);

    connect(tb_queen, SIGNAL(clicked()), this, SLOT(figureSelected()));
    connect(tb_castle, SIGNAL(clicked()), this, SLOT(figureSelected()));
    connect(tb_knight, SIGNAL(clicked()), this, SLOT(figureSelected()));
    connect(tb_bishop, SIGNAL(clicked()), this, SLOT(figureSelected()));
}

void SelectFigure::figureSelected()
{
    QString objectName = sender()->objectName();
    newFigure(objectName);
    close();
}


//-------------------------
//----ChessWindow----------
//-------------------------
ChessWindow::ChessWindow(Figure::GameType type, bool enableSound_ , QWidget *parent)
    : QMainWindow(parent)
    , enabledSound(enableSound_)
    , movesCount(0)
{
    ui_.setupUi(this);
    setAttribute(Qt::WA_DeleteOnClose);
    setFixedSize(610,555);
    setWindowIcon(QIcon(QPixmap(":/chessplugin/figures/Chess.png")));
    setStyleSheet("QMainWindow *{background-color: #ffffe7; color: black; }"
              "QMenu  {background-color: #ffa231;}"
              "QMenu::item { background-color: #ffa231; padding: 1px; padding-right: 5px; padding-left: 18px; }"
              "QMenu::item:selected:!disabled {background-color: #ffeeaf; border: 1px solid #74440e; }"
              "QMenu::item:disabled {color: #646464; }"
              "QMenu::separator { height: 2px; background: yellow;}"
              "QMenu::item:checked { background-color: #ffeeaf;}"
              "QPushButton { background-color: #e9edff;}"
              "QPushButton:hover { background-color: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1, stop: 0 #e9edff, stop: 1 black)}");

    model_ = new BoardModel(type, this);
    model_->reset();
    ui_.tv_board->setModel(model_);
    if(type == Figure::WhitePlayer)
        ui_.tv_board->setCurrentIndex(model_->kingIndex());
    else
        ui_.tv_board->setCurrentIndex(model_->invert(model_->kingIndex()));

    ui_.te_moves->setText(tr("    White    Black\n"));

    connect(model_, SIGNAL(move(int,int,int,int, QString)), this, SIGNAL(move(int,int,int,int, QString)));
    connect(model_, SIGNAL(move(int,int,int,int, QString)), this, SLOT(addMove(int,int,int,int)));
    connect(model_, SIGNAL(figureKilled(Figure*)), this, SLOT(figureKilled(Figure*)));
    connect(model_, SIGNAL(needNewFigure(QModelIndex, QString)), this, SLOT(needNewFigure(QModelIndex, QString)));

    createMenu();
}

void ChessWindow::closeEvent(QCloseEvent *e)
{
    e->ignore();
    emit closeBoard();
}

void ChessWindow::moveRequest(int oldX, int oldY, int newX, int newY, const QString& figure) {
    bool b = model_->moveRequested(oldX, oldY, newX, newY);
    ui_.tv_board->viewport()->update();
    if(!b)
        emit error();
    else {
        emit moveAccepted();
        addMove(oldX, oldY, newX, newY);
    }
    if(!figure.isEmpty())
        model_->updateFigure(model_->index(7-newY,newX), figure);//7- - for compatibility with tkabber

    int state = model_->checkGameState();
    if(state == 2)
        emit lose();
    else if(state == 1)
        emit draw();
}

void ChessWindow::addMove(int oldX, int oldY, int newX, int newY) {
    Figure *f = 0;
    if(model_->gameType_ == Figure::WhitePlayer) { //for compatibility with tkabber
        oldY = 7-oldY;
        newY = 7-newY;
        f = model_->findFigure(model_->index(newY, newX));
    }
    else if(model_->gameType_ == Figure::BlackPlayer) {
        f = model_->findFigure(model_->index(7-newY, newX));
        oldX = 7-oldX;
        newX = 7-newX;
    }

    QString type = " ";
    if(f)
        type = f->typeString();

    QString text = ui_.te_moves->toPlainText();
    int moveNumber = movesCount+2;
    if(moveNumber&1) {
        text += "   "+type[0]+model_->headerData(oldX, Qt::Horizontal).toString().toLower()+model_->headerData(oldY, Qt::Vertical).toString()+"-"
            +model_->headerData(newX, Qt::Horizontal).toString().toLower()+model_->headerData(newY, Qt::Vertical).toString()+"\n";
    }
    else {
        text += QString::number(moveNumber/2)+". "+type[0]+model_->headerData(oldX, Qt::Horizontal).toString().toLower()
            +model_->headerData(oldY, Qt::Vertical).toString()+"-"+model_->headerData(newX, Qt::Horizontal).toString().toLower()
            +model_->headerData(newY, Qt::Vertical).toString();
    }

    ui_.te_moves->setText(text);
    QTextCursor cur = ui_.te_moves->textCursor();
    cur.setPosition(text.length());
    ui_.te_moves->setTextCursor(cur);
    movesCount++;
}

void ChessWindow::createMenu() {
    QMenuBar *menuBar = ui_.menubar;
    menuBar->setStyleSheet("QMenuBar::item {background-color: #ffffe7; border-radius: 1px; border: 1px solid #74440e; color: black;"
                   "spacing: 10px; padding: 1px 4px; background: transparent; }"
                   "QMenuBar::item:selected { background-color: #ffeeaf; color: black;  }"
                   "QMenuBar::item:pressed { background: #ffeeaf; color: black;  }");

    QAction *loadAction = new QAction(tr("Load game"), menuBar);
    QAction *saveAction = new QAction(tr("Save game"), menuBar);
    QAction *quitAction = new QAction(tr("Quit"), menuBar);
    loseAction = new QAction(tr("Resign"), menuBar);
    QAction *soundAction = new QAction(tr("Enable sound"),menuBar);
    soundAction->setCheckable(true);
    soundAction->setChecked(enabledSound);

    QMenu *fileMenu = menuBar->addMenu(tr("File"));
    QMenu *gameMenu = menuBar->addMenu(tr("Game"));

    fileMenu->addAction(loadAction);
    fileMenu->addAction(saveAction);
    fileMenu->addSeparator();
    fileMenu->addAction(quitAction);
    gameMenu->addAction(loseAction);
    gameMenu->addSeparator();
    gameMenu->addAction(soundAction);

    connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));
    connect(quitAction, SIGNAL(triggered()), this, SLOT(close()), Qt::QueuedConnection);
    connect(loseAction, SIGNAL(triggered()), this, SIGNAL(lose()));
    connect(soundAction, SIGNAL(triggered(bool)), this, SIGNAL(toggleEnableSound(bool)));
}

void ChessWindow::load() {
    QString fileName = QFileDialog::getOpenFileName(0,tr("Load game"), "", tr("*.chs"));
    if(fileName.isEmpty()) return;

    QFile file(fileName);
    if(file.open(QIODevice::ReadOnly)) {
        QTextStream in(&file);
        in.setCodec("UTF-8");
        QString settings = in.readAll();
        model_->loadSettings(settings);
        if(model_->gameType_ == Figure::WhitePlayer)
            ui_.tv_board->setCurrentIndex(model_->kingIndex());
        else
            ui_.tv_board->setCurrentIndex(model_->invert(model_->kingIndex()));

        emit load(settings);
        ui_.te_moves->setText(tr("  White     Black\n"));
        movesCount = 0;
    }
}

void ChessWindow::loadRequest(const QString& settings) {
    model_->loadSettings(settings, false);
    if(model_->gameType_ == Figure::WhitePlayer)
        ui_.tv_board->setCurrentIndex(model_->kingIndex());
    else
        ui_.tv_board->setCurrentIndex(model_->invert(model_->kingIndex()));

    ui_.te_moves->setText(tr("  White     Black\n"));
    movesCount = 0;
}

void ChessWindow::save() {
    QString fileName = QFileDialog::getSaveFileName(0,tr("Save game"), "", tr("*.chs"));
    if(fileName.isEmpty())
        return;
    if(fileName.right(4) != ".chs")
        fileName.append(".chs");

    QFile file(fileName);
    if(file.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
        QTextStream out(&file);
        out.setCodec("UTF-8");
        out.setGenerateByteOrderMark(false);
        out << model_->saveString();
    }
}

void ChessWindow::figureKilled(Figure *figure) {
    QPixmap pix = figure->getPixmap().scaled(24,24, Qt::KeepAspectRatio, Qt::SmoothTransformation);
    QLabel *label = new QLabel;
    label->setFixedSize(24,24);
    label->setPixmap(pix);
    if(figure->gameType() == Figure::WhitePlayer) {
        ui_.white_layout->addWidget(label);
        if(!model_->myMove)
            ui_.tv_board->setCurrentIndex(model_->kingIndex());
    }
    else {
        ui_.black_layout->addWidget(label);
        if(!model_->myMove)
            ui_.tv_board->setCurrentIndex(model_->invert(model_->kingIndex()));
    }
}

void ChessWindow::needNewFigure(QModelIndex index, const  QString& player) {
    tmpIndex_ = index;
    if(model_->gameType_ == Figure::BlackPlayer)
        index = model_->invert(index);

    SelectFigure *sf = new SelectFigure(player, this);
    QPoint pos = ui_.tv_board->pos();
    pos.setX(pos.x() + index.column()*50 + 4);
    pos.setY(pos.y() + index.row()*50 + 25);
    sf->move(pos);
    connect(sf, SIGNAL(newFigure(QString)), this, SLOT(newFigure(QString)));
    sf->show();
}

void ChessWindow::newFigure(QString figure) {
    model_->updateFigure(tmpIndex_, figure);
}

void ChessWindow::youWin()
{
    model_->gameState_ = 2;
    model_->updateView();
    loseAction->setEnabled(false);
}

void ChessWindow::youLose()
{
    model_->gameState_ = 3;
    model_->updateView();
}

void ChessWindow::youDraw()
{
    model_->gameState_ = 1;
    model_->updateView();
}
