#ifndef CHESSPLUGIN_H
#define CHESSPLUGIN_H

#include "chessplugin_global.h"
#include "drawableDataInterface.h"
#include <qgraphicsitem.h>
#include "DrawableObjectGraphicsItem.h"
#include <qparallelanimationgroup.h>
#include <qpainter.h>


class GraphicsQueen;

/**
* @brief Плагин, показывающий шахматное поле по матрице int[8][8], полученной из отладчика,
* для иллюстрации задачи о восьми ферзях.
* В этой матрице 0 - значит пустая клетка, 1 - ферзь.
* Ферзи могут находиться только по одному в столбце.
* Если в результате совершения шага трассировки единица в столбце матрицы переместилась (старая исчезла и появилась новая в другой строке),
* то показывается анимация по перемещению ферзя в этом столбце шахматного поля.
*/

/* Простой тест для демонстрации - можно собрать в отдельном проекте и потрассировать с использованием плагина.
void move(int field[8][8], int col, int newRow)
{
	for(int i = 0; i < 8; i++)
	{
		if(i == newRow)
			field[i][col] = 1;
		else
			field[i][col] = 0;
	}
}

void chessTest()
{
	int field[8][8] = {0};

	field[3][3] = 1;
	
	move(field, 3, 0);
	move(field, 3, 1);
}
*/

class CHESSPLUGIN_EXPORT ChessPlugin : public QObject, DrawableDataInterface
{
	Q_OBJECT
	Q_INTERFACES(DrawableDataInterface)

private:
	char** field; // Текущее состояние поля
	char** oldField; // Предыдущее состояние поля
	Variable* matrix; // Матрица, полученная через data provider

	QGraphicsRectItem* graphicsField; // Графический элемент, представляющий шахматное поле (в нём вложены ферзи)
	GraphicsQueen*** graphicsQueens; // Матрица указателей на сами ферзи - необходима для точного запоминания их положений при анимации

	QParallelAnimationGroup *animation; // Объект анимации (передвигание ферзей)

	/** 
     * @brief Проверка, что полученный элемент действительно является матрицей символов 8х8
	 * \param data контейнер всех полученных переменных (в этом случае содержит один элемент - саму матрицу)
	 */
	bool checkCorrectData(const QList<Variable*> &  data);

	void saveOldField(); // Копирование field в oldField
public:

	static const int CELL_COUNT = 8;
	static const int CELL_SIZE = 30;
	static const int FIELD_SIZE = CELL_SIZE * CELL_COUNT;

	ChessPlugin();
	~ChessPlugin();

	/**
	*  Рассчёт координат
	*/
	void calcGeometry();
	void calcDefaultGeometry(DataProvider* provider) { calcGeometry(); };

	/** 
	 * Инициализация данными о переменных
	 * \param provider поставщик данных
	 * \param result результат получения данных из отладчика
	 * \param variables контейнер с переменными (если нужен особый набор)
	 */
	bool setData(TraceDataProvider* provider, GET_VARIABLES_RESULT result, QList<Variable*> & variables);

	/** 
	 * Рисование
	 */
	QGraphicsItem* createGraphicsItem();

	void updateGraphicsItem();

	/** 
	 * Получение имени объекта
	 * \return имя
	 */
	QString getName() const;

	/** 
	 * Требует ли особый набор данных
	 * \return требует ли особый набор данных
	 */
	bool isRequiredCustomVariables() const;

	QStringList requiredCustomVariables() const;

	/** 
	 * Действия при нажатии на область объекта
	 * \param [in] id идентификатор элемента, который был нажат
	 * \return идентификатор элемента, который должен быть подсвечен в графах и других представлениях
	 */
	int onElementClicked(int id);

	/** 
	 * Сворачивает или разворачивает все вершины
	 * \param minimized свернуть или развернуть
	 */
	void setAllMinimized(bool minimized);

	/**
	* Подсветка объекта, представляющего переменную с заданным id
	* \param id идентификатор переменной
	* \param primitives примитивы
	*/
	void markItem(int id);

	bool isPlugin() const { return true; };

	bool isRepresentsFunctionResult() const { return false; };

	/** 
	 * Получение имён функций, результат которых представляет плагин
	 * \return список имёт функций
	 */
	QStringList getRepresentedFunctionNames() const { return QStringList(); };

	/** 
	 * Получение необходимых параметров представляемой функции из поставщика данных
	 * \param functionName имя функции
	 * \param provider поставщик данных
	 */
	void setFunctionParams(QString & functionName, TraceDataProvider* provider) {};
	
	QAnimationGroup* getAnimationAfterStep();

	QLayout* getUIAdditionalWidgets();

public slots:

	void someAction();

};

class GraphicsQueen : public QGraphicsObject
{
	Q_OBJECT
public:
	QRectF boundingRect() const
	{
		return QRectF(0, 0, ChessPlugin::CELL_SIZE, ChessPlugin::CELL_SIZE);
	}

	void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
	{
		painter->setBrush(QImage("queen.png").scaled(ChessPlugin::CELL_SIZE, ChessPlugin::CELL_SIZE));
		painter->drawRect(0, 0, ChessPlugin::CELL_SIZE, ChessPlugin::CELL_SIZE);
	}
};


#endif // CHESSPLUGIN_H
