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

 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 "TreeDataWriter.h"
#include <iostream>

#ifdef NS_INFOMAP
namespace infomap {
#endif

TreeDataWriter::TreeDataWriter(const TreeData& tree) :
    m_tree(tree)
{
}

/**
 * Print the module indices down to the leaf nodes like:
 * 0:		First super module
 * 0:0:		First sub module
 * 0:0:0:	Leaf node
 * 0:0:1:	Leaf node
 * 0:1:		Second sub module
 * 0:1:0:	Leaf node
 * 1:		Second super module
 * 1:0:		...
 */
void
TreeDataWriter::writeTree(std::ostream& out, bool collapseLeafs)
{
    uint oldDepth = 0;
    std::vector<unsigned int> indexStack;
    const NodeBase* root = m_tree.root();

    for (NodeBase::const_pre_depth_first_iterator nodeIt(root);	!nodeIt.isEnd(); ++nodeIt)
    {
        if (collapseLeafs)
        {
            if (nodeIt->isLeaf())
            {
                if (nodeIt->next == 0)
                {
                    //					for (unsigned int i = 0; i < indexStack.size(); ++i)
                    //						out << "  ";
                    //					out << "(" << nodeIt->parent->childDegree() << ")" << std::endl;
                    out << "(" << nodeIt->parent->childDegree() << ")\t(node id: " << *nodeIt->parent << ")" << std::endl;
                }

                continue;
            }
        }

        if (nodeIt.base() == root)
        {
            //			indexStack.push_back(0);
        }
        else if (nodeIt.depth() == oldDepth) // ->next
        {
            ++indexStack.back();
        }

        else if (nodeIt.depth() > oldDepth) // ->firstChild
        {
            indexStack.push_back(0);
        }

        else // ->parent[->parent->...]->sibling
        {
            while (indexStack.size() > nodeIt.depth())
            {
                indexStack.pop_back();
            }

            ++indexStack.back();
        }

        oldDepth = nodeIt.depth();

        //		writeIndexStack(out, indexStack);
        std::copy(indexStack.begin(), indexStack.end(), std::ostream_iterator<uint>(out,":"));

        if (collapseLeafs && nodeIt.next()->isLeaf())
        {
            continue;
        }

        out << "\t(node id: " << *nodeIt << ")" << std::endl;
    }
}

void
TreeDataWriter::writeTopGraph(std::ostream& out)
{
    (void)out; // to avoid compiler warning
    //	const NodeBase& root = *m_tree.root();
    //	for (NodeBase::sibling_iterator childIt(root.begin_child()); childIt != root.end_child(); ++childIt)
    //	{
    //		const NodeBase& node = *childIt;
    //		out << "Node " << node << std::endl;
    //		for (NodeBase::const_edge_iterator outEdgeIt(node.begin_outEdge()); outEdgeIt != node.end_outEdge(); ++outEdgeIt)
    //		{
    //			EdgeType& edge = **outEdgeIt;
    //			out << "\t--> " << edge.target << ", flow: " << edge.data.flow << std::endl;
    //		}
    //	}
}

void
TreeDataWriter::writeLeafNodes(std::ostream& out)
{
    out << "Writing leaf network with " << m_tree.numLeafNodes() << " nodes and " << m_tree.numLeafEdges() << " edges.\n";
    unsigned int i = 0;

    for (TreeData::const_leafIterator nodeIt(m_tree.begin_leaf());
            nodeIt != m_tree.end_leaf(); ++nodeIt, ++i)
    {
        out << i << " (" << **nodeIt << ")" << std::endl;
    }
}

#ifdef NS_INFOMAP
}
#endif
