#include "command.h"
#include "griddesigner.h"
#include "settings.h"

NewGridNode::NewGridNode(GridDesigner* designer, double x, double y, int compId, const QString& name)
{
	_x = x;
	_y = y;
	_designer = designer;
	_compId = compId;
	_name = name;

	_component = new GridNode(NULL, _compId);
	//_component = new GridNode(_designer->scene(), _compId);
	_component->setPower(AppSettings::defaultCPUPower());
	_component->setName(_name);
	//_component->hide();
	
	setExecuted(false);
}

NewGridNode::~NewGridNode()
{
	if(!executed()) {
		delete _component;
		_component = NULL;
	}
}

void NewGridNode::execute()
{
	Q_ASSERT(!executed());

	double x, y;
	
	x = _x - _component->imageWidth() / 2;
	y = _y - _component->imageHeight() / 2;
	
	if(x < 0) {
		x = 0;
	}
	if(y < 0) {
		y = 0;
	}
	
	_component->setPos(QPointF(x, y));
	//_component->show();
	_designer->scene()->addItem(_component);
	
	_designer->setSelection(_component);
	_component->setSelected(true);
	setExecuted(true);
}

void NewGridNode::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	if(_component) {
		//_component->hide();
		_designer->scene()->removeItem(_component);
	}
}

NewLink::NewLink(GridDesigner* designer, double x, double y, int compId, const QString& name)
{
	_x = x;
	_y = y;
	_designer = designer;
	_compId = compId;
	_name = name;

	_component = new Link(NULL, _compId);
	//_component = new Link(_designer->scene(), _compId);
	_component->setBandwidth(AppSettings::defaultBandwidth());
	_component->setLatency(AppSettings::defaultLatency());
	_component->setName(_name);
	//_component->hide();
	
	setExecuted(false);
}

NewLink::~NewLink()
{
	if(!executed()) {
		delete _component;
		_component = NULL;
	}
}

void NewLink::execute()
{
	Q_ASSERT(!executed());

	double x, y;
	
	x = _x - _component->imageWidth() / 2;
	y = _y - _component->imageHeight() / 2;
	
	if(x < 0) {
		x = 0;
	}
	if(y < 0) {
		y = 0;
	}
	
	_component->setPos(QPointF(x, y));
	//_component->show();
	_designer->scene()->addItem(_component);
	
	_designer->setSelection(_component);
	_component->setSelected(true);
	setExecuted(true);
}

void NewLink::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	if(_component) {
		//_component->hide();
		_designer->scene()->removeItem(_component);
	}
}

NewConnection::NewConnection(GridDesigner* designer, DesignerComponent* src, DesignerComponent* dest, int compId)
{
	_designer = designer;
	_compId = compId;
	_src = src;
	_dest = dest;
	
	_component = new Connection(NULL, _compId);
	//_component = new Connection(_designer->scene(), _compId);
	//_component->hide();
	
	setExecuted(false);
}

NewConnection::~NewConnection()
{
	if(!executed()) {
		delete _component;
		_component = NULL;
	}
}

void NewConnection::execute()
{
	Q_ASSERT(!executed());

	_component->setSource(_src);
	_component->setDestination(_dest);
	//_component->show();
	_designer->scene()->addItem(_component);
	
	_designer->setSelection(_component);
	_component->setSelected(true);
	setExecuted(true);
}

void NewConnection::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	if(_component) {
		//_component->hide();
		_designer->scene()->removeItem(_component);
	}
}

//////////////////////////////////////////////////////////////////////////////////////////
MoveItems::MoveItems(GridDesigner* designer, DesignerItemMap items, QPointF offset)
{
	_designer = designer;
	_items = items;
	_offset = offset;
	_movPoints = items.movingPoints();
	_selPoints = items.selectedPoints();

	setExecuted(false);
}

MoveItems::~MoveItems()
{
}

void MoveItems::execute()
{
	Q_ASSERT(!executed());

	_designer->setSelection(_items);
	_items.setMovingPoints(_movPoints);
	_items.setSelectedPoints(_selPoints);
	_items.moveBy(_offset);
	_movPoints = _items.movingPoints();
	
	setExecuted(true);
}

void MoveItems::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	_designer->setSelection(_items);
	_items.setMovingPoints(_movPoints);
	_items.setSelectedPoints(_selPoints);
	_items.moveBy(-_offset);
	_movPoints = _items.movingPoints();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
DeleteItems::DeleteItems(GridDesigner* designer, DesignerItemMap items)
{
	_originalItems = items;
	_items = items;
	_designer = designer;
	_designer->addConnectionItems(_items);
}

DeleteItems::~DeleteItems()
{
	if(executed()) {
		_items.deleteAllItems();
	}
}
	
void DeleteItems::execute()
{
	Q_ASSERT(!executed());

	setExecuted(true);
	//_items.hide();
	_items.removeFromScene();
}

void DeleteItems::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	//_items.show();
	_items.addToScene(_designer->scene());

	_designer->setSelection(_originalItems);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
AddConnectionPoint::AddConnectionPoint(GridDesigner* designer, Connection* conn, QPointF cutPoint, QPointF newPoint)
{
	_designer = designer;
	_conn = conn;
	_cutPoint = cutPoint;
	_newPoint = newPoint;
}

AddConnectionPoint::~AddConnectionPoint()
{

}

void AddConnectionPoint::execute()
{
	Q_ASSERT(!executed());

	_designer->clearSelection();

	_conn->addPoint(_cutPoint, _newPoint);
	if(!_newPoint.isNull()) {
		_conn->selectPoint(_newPoint);
	}
	else {
		_conn->selectPoint(_cutPoint);
	}
// 	_conn->addPoint(_cutPoint);
// 	if(!_newPoint.isNull()) {
// 		PointList ps;
// 		QPointF movePos;
// 		ps.append(_cutPoint);
// 		_conn->setMovingPoints(ps);
// 		movePos = _newPoint - _cutPoint;
// 		_conn->moveBy(movePos.x(), movePos.y());
// 		_conn->selectPoint(_newPoint);
// 	}
// 	else {
// 		_conn->selectPoint(_cutPoint);
// 	}

	_designer->addSelection(_conn);

	setExecuted(true);
}

void AddConnectionPoint::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	if(!_conn->removePoint(_newPoint.isNull() ? _cutPoint : _newPoint))
		qDebug("AddConnectionPoint::undo: Cannot delete point\n");
	_designer->clearSelection();
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
RemoveConnectionPoint::RemoveConnectionPoint(GridDesigner* designer, Connection* conn, QPointF delPoint)
{
	_designer = designer;
	_conn = conn;
	_delPoint = delPoint;
}

RemoveConnectionPoint::~RemoveConnectionPoint()
{
}

void RemoveConnectionPoint::execute()
{
	Q_ASSERT(!executed());

	_conn->removePoint(_delPoint, &_removedPoint);
	_designer->clearSelection();
	setExecuted(true);
}

void RemoveConnectionPoint::undo()
{
	Q_ASSERT(executed());

	setExecuted(false);
	_conn->addPoint(_removedPoint, _delPoint);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
ChangeLinkProperties::ChangeLinkProperties(GridDesigner*, Link* link, const QString& name, uint band, double lat)
{
	_link = link;
	_name = name;
	_band = band;
	_lat = lat;
}

ChangeLinkProperties::~ChangeLinkProperties()
{
}
	
void ChangeLinkProperties::execute()
{
	Q_ASSERT(!executed());

	_oldName = _link->name();
	_oldBand = _link->bandwidth();
	_oldLat = _link->latency();
	
	_link->setName(_name);
	_link->setBandwidth(_band);
	_link->setLatency(_lat);

	setExecuted(true);
}

void ChangeLinkProperties::undo()
{
	Q_ASSERT(executed());

	_link->setName(_oldName);
	_link->setBandwidth(_oldBand);
	_link->setLatency(_oldLat);

	setExecuted(false);
}

//////////////////////////////////////////////////////////////////////////////////////////////////////
ChangeNodeProperties::ChangeNodeProperties(GridDesigner*, GridNode* node, const QString& name, uint pow)
{
	_node = node;
	_name = name;
	_pow = pow;
}

ChangeNodeProperties::~ChangeNodeProperties()
{
}

void ChangeNodeProperties::execute()
{
	Q_ASSERT(!executed());

	_oldName = _node->name();
	_oldPow = _node->power();
	
	_node->setName(_name);
	_node->setPower(_pow);

	setExecuted(true);
}

void ChangeNodeProperties::undo()
{
	Q_ASSERT(executed());

	_node->setName(_oldName);
	_node->setPower(_oldPow);

	setExecuted(false);
}

