/**********************************************************************************

 Infomap software package for multi-level network clustering

 Copyright (c) 2013, 2014 Daniel Edler, Martin Rosvall
 
 For more information, see <http://www.mapequation.org>
 

 This file is part of Infomap software package.

 Infomap software package is free software: you can redistribute it and/or modify
 it under the terms of the GNU Affero General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 Infomap software package 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 Affero General Public License for more details.

 You should have received a copy of the GNU Affero General Public License
 along with Infomap software package.  If not, see <http://www.gnu.org/licenses/>.

**********************************************************************************/


#include "Node.h"
#include "../utils/Logger.h"

#include "InfomapBase.h"

#ifdef NS_INFOMAP
namespace infomap
{
#endif

long NodeBase::s_nodeCount = 0;
unsigned long NodeBase::s_UID = 0;

SubStructure::SubStructure() : subInfomap(0), exploredWithoutImprovement(false) {}
SubStructure::~SubStructure() {}

NodeBase::NodeBase()
:	id(s_UID++),
 	name(),
 	index(0),
 	originalIndex(0),
	parent(0),
	previous(0),
	next(0),
	firstChild(0),
	lastChild(0),
	owner(0),
	codelength(0.0),
	dirty(false),
	m_subStructure(),
	m_childDegree(0),
	m_childrenChanged(false),
	m_numLeafMembers(1)
{
	++s_nodeCount;
}

NodeBase::NodeBase(std::string name)
:	id(s_UID++),
 	name(name),
 	index(0),
 	originalIndex(0),
	parent(0),
	previous(0),
	next(0),
	firstChild(0),
	lastChild(0),
	owner(0),
	codelength(0.0),
	dirty(false),
	m_subStructure(),
	m_childDegree(0),
	m_childrenChanged(false),
	m_numLeafMembers(1)
{
	++s_nodeCount;
}

NodeBase::NodeBase(const NodeBase& other)
:	id(s_UID++),
 	name(other.name),
 	index(0),
 	originalIndex(0),
	parent(0),
	previous(0),
	next(0),
	firstChild(0),
	lastChild(0),
	owner(0),
	codelength(0.0),
	dirty(false),
	m_subStructure(),
	m_childDegree(0),
	m_childrenChanged(false),
	m_numLeafMembers(1)
{
	++s_nodeCount;
}

NodeBase::~NodeBase()
{
	deleteChildren();

	if (next != 0)
		next->previous = previous;
	if (previous != 0)
		previous->next = next;
	if (parent != 0)
	{
		if (parent->firstChild == this)
			parent->firstChild = next;
		if (parent->lastChild == this)
			parent->lastChild = previous;
	}

	// Delete outgoing edges.
	// TODO: Renders ingoing edges invalid. Assume or assert that all nodes on the same level are deleted?
	for (NodeBase::edge_iterator outEdgeIt(begin_outEdge());
			outEdgeIt != end_outEdge(); ++outEdgeIt)
	{
		delete *outEdgeIt;
	}

	--s_nodeCount;
}

void NodeBase::deleteChildren()
{
	if (firstChild == 0)
		return;

	NodeBase::sibling_iterator nodeIt = begin_child();
	do
	{
		NodeBase* n = nodeIt.base();
		++nodeIt;
		delete n;
	}
	while (nodeIt.base() != 0);

	firstChild = 0;
	lastChild = 0;
	m_childDegree = 0;
}

void NodeBase::calcChildDegree()
{
	m_childrenChanged = false;
	if (firstChild == 0)
		m_childDegree = 0;
	else if (firstChild == lastChild)
		m_childDegree = 1;
	else
	{
		m_childDegree = 0;
		for (NodeBase::sibling_iterator childIt(begin_child()), endIt(end_child());
				childIt != endIt; ++childIt, ++m_childDegree);
	}
}


const NodeBase* NodeBase::getSubInfomapRoot() const
{
	return getSubInfomap() ? getSubInfomap()->root() : 0;
}

NodeBase* NodeBase::getSubInfomapRoot()
{
	return getSubInfomap() ? getSubInfomap()->root() : 0;
}


#ifdef NS_INFOMAP
}
#endif
