#include "chessplugin.h"
#include "Variable.h"
#include <qcolor.h>
#include <qregexp.h>
#include "qimage.h"
#include <qpainter.h>
#include <qsize.h>
#include "DrawableObjectGraphicsItem.h"
#include <qrect.h>
#include <qpropertyanimation.h>
#include <qboxlayout.h>
#include <qcheckbox.h>
#include <qpushbutton.h>
#include <qinputdialog.h>

ChessPlugin::ChessPlugin()
{
	matrix = NULL;
	animation = NULL;

	field = new char*[CELL_COUNT];
	for(int i = 0 ; i < CELL_COUNT; i++)
		field[i] = new char[CELL_COUNT];

	oldField = new char*[CELL_COUNT];
	for(int i = 0 ; i < CELL_COUNT; i++)
		oldField[i] = new char[CELL_COUNT];

	graphicsQueens = new GraphicsQueen**[CELL_COUNT];
	for(int i = 0 ; i < CELL_COUNT; i++)
		graphicsQueens[i] = new GraphicsQueen*[CELL_COUNT];
}

ChessPlugin::~ChessPlugin()
{
	for(int i = 0 ; i < CELL_COUNT; i++)
	{
		delete [] field[i];
		delete [] oldField[i];
		delete [] graphicsQueens[i];
	}
	delete [] field;
	delete [] oldField;
	delete [] graphicsQueens;
}

void ChessPlugin::saveOldField()
{
	for(int i = 0; i < CELL_COUNT; i++)
		for(int j = 0; j < CELL_COUNT; j++)
			oldField[i][j] = field[i][j];
}

void ChessPlugin::calcGeometry()
{
	setSize(QSizeF(CELL_COUNT * CELL_SIZE, CELL_COUNT * CELL_SIZE));
}

bool ChessPlugin::checkCorrectData(const QList<Variable*> & data)
{
	QRegExp regExp("int \\[8\\]\\[8\\]");
	return regExp.exactMatch(data.first()->getType());
}

bool ChessPlugin::setData(TraceDataProvider* provider, GET_VARIABLES_RESULT result, QList<Variable*> & variables)
{
	if(result == allChanged)
	{
		if(!checkCorrectData(variables))
			return false;

		matrix = variables.first();
	}

	int rowIndex = 0;
	int colIndex = 0;

	saveOldField();

	for(QList<Variable*>::const_iterator i = matrix->getChilds().constBegin(); i != matrix->getChilds().constEnd(); ++i)
	{
		Variable* row = *i;
		colIndex = 0;
		for(QList<Variable*>::const_iterator j = row->getChilds().constBegin(); j != row->getChilds().constEnd(); ++j)
		{
			field[rowIndex][colIndex] = (*j)->getValue().toInt();
			colIndex++;
		}
		rowIndex++;
	}
	return true;
}

QGraphicsItem* ChessPlugin::createGraphicsItem()
{
	graphicsField = new QGraphicsRectItem(0,0, FIELD_SIZE, FIELD_SIZE);
	graphicsField->setBrush(QBrush(QImage("field.jpg").scaled(FIELD_SIZE, FIELD_SIZE)));
	
	for(int i = 0; i < CELL_COUNT; i++)
	{
		for(int j = 0; j < CELL_COUNT; j++)
		{
			if(field[i][j] == 1)
			{
				GraphicsQueen* queen = new GraphicsQueen();
				queen->setPos(CELL_SIZE * j, CELL_SIZE * i);
				queen->setParentItem(graphicsField);
				graphicsQueens[i][j] = queen;
			}
			else
				graphicsQueens[i][j] = NULL;
		}
	}
	graphicsField->setFlags(QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
	
	return graphicsField;
}

void ChessPlugin::updateGraphicsItem()
{
	animation = new QParallelAnimationGroup();

	for(int i = 0; i < CELL_COUNT; i++)
	{
		for(int j = 0; j < CELL_COUNT; j++)
		{
			if(field[i][j] == 1 && oldField[i][j] != 1)
			{
				bool queenExists = false;
				for(int k = 0; k < CELL_COUNT; k++)
				{
					if(oldField[k][j] == 1 && k != i)
					{// Если изменилось положение ферзя (найдена новая единица в строке)
						queenExists = true;

						GraphicsQueen* queen = graphicsQueens[k][j];
						graphicsQueens[i][j] = queen;
						graphicsQueens[k][j] = NULL;

						QPropertyAnimation *moveAnim = new QPropertyAnimation(queen, "pos");

						moveAnim->setStartValue(queen->pos());
						moveAnim->setEndValue(QPointF(queen->pos().x(), CELL_SIZE * i));
						moveAnim->setDuration(1200);
						animation->addAnimation(moveAnim);
					}
				}
				if(!queenExists)
				{// Добавилась новая единица (до этого её в столбце не было)
					GraphicsQueen* queen = new GraphicsQueen();
					queen->setPos(CELL_SIZE * j, CELL_SIZE * i);
					queen->setParentItem(graphicsField);
					graphicsQueens[i][j] = queen;
				}
			}
		}
	}
}

QString ChessPlugin::getName() const
{
	return "Chess";
}

bool ChessPlugin::isRequiredCustomVariables() const
{
	return true;
}

QStringList ChessPlugin::requiredCustomVariables() const
{
	QStringList list;
	list << "Matrix - chess field";
	return list;
}

int ChessPlugin::onElementClicked(int id)
{
	return -1;
}

void ChessPlugin::setAllMinimized(bool minimized)
{
}

void ChessPlugin::markItem(int id)
{
}

QAnimationGroup* ChessPlugin::getAnimationAfterStep()
{
	return animation;
}

QLayout* ChessPlugin::getUIAdditionalWidgets()
{
	QVBoxLayout* layout = new QVBoxLayout();
	QCheckBox* check = new QCheckBox();
	check->setText("Бессмысленный элемент");
	QPushButton* button = new QPushButton();
	button->setText("Бессмысленное действие");
	QObject::connect(button, SIGNAL(clicked()), this, SLOT(someAction()));

	layout->addWidget(check);
	layout->addWidget(button);
	return layout;
}

void ChessPlugin::someAction()
{
	QInputDialog::getText(NULL, "Бессмысленность", "Вообще");
}

 Q_EXPORT_PLUGIN2(chessPlugin, ChessPlugin);