#include "connection.h"
#include "globals.h"

Connection::Connection(scene::ISceneManager* smgr, Entity* from, Entity* to, bool constraining)
	: Entity(smgr, 0.5f*(from->getPos() + to->getPos())), from(from), to(to), constraining(constraining),
	potentialDuplicate(true)
{
	sceneNode->setMaterialTexture(0, device->getVideoDriver()->getTexture("../data/img/connection.png"));

	stretchBetweenNodes();
}

void Connection::setTo(Entity* newTo)
{
	potentialDuplicate = true;
	to = newTo;
	stretchBetweenNodes();
}

void Connection::startConstraining()
{
	constraining = true;
}

// Set length to the distance between the from and to entities
void Connection::stretchBetweenNodes()
{
	core::vector2df d = from->getPos() - to->getPos();
	connectionLength = d.getLength();
	float nodeWidth = sceneNode->getBoundingBox().getExtent().X;
	sceneNode->setScale(core::vector3df(connectionLength / nodeWidth, 0.2f, 1.0f));
	updateRotation();
}

void Connection::updateRotation()
{
	core::vector2df rot = to->getPos() - from->getPos();
	rot.normalize();
	sceneNode->setRotation(core::vector3df(0, 0, atan2(rot.Y, rot.X) * 180.0f / PI));
}

void Connection::update()
{
	// Move into centre of entities
	setPos(0.5f*(from->getPos() + to->getPos()));

	if (constraining)
	{
		// Constrain distance between entities
		core::vector2df separation = to->getPos() - from->getPos();
		separation.normalize();
		separation *= connectionLength;
		to->setPos(getPos() + separation * 0.5f);
		from->setPos(getPos() - separation * 0.5f);
		updateRotation();
	}
	else
	{
		stretchBetweenNodes();
	}
}

Connection::~Connection()
{
	
}

bool Connection::operator<(const Connection* other) const
{
	return cmp(other) < 0;
}

bool Connection::operator>(const Connection* other) const
{
	return cmp(other) > 0;
}
bool Connection::operator<=(const Connection* other) const
{
	return cmp(other) <= 0;
}

bool Connection::operator>=(const Connection* other) const
{
	return cmp(other) >= 0;
}

int Connection::cmp(const Connection* other) const
{
	// Just need some arbitrary node-based order
	if (from < other->from)
	{
		return -1;
	}
	else if (from > other->from)
	{
		return +1;
	}

	if (to < other->to)
	{
		return -1;
	}
	else if (to > other->to)
	{
		return +1;
	}

	return 0;
}


bool Connection::duplicateOf(Connection* other)
{
	return (from->getId() == other->from->getId()
			&& to->getId() == other->to->getId())
			|| (to->getId() == other->from->getId()
			&& from->getId() == other->to->getId());
}