package edu.claflin.finder.algo.clustering;

import static edu.claflin.finder.Global.getLogger;
import java.util.ArrayList;

import edu.claflin.finder.algo.ArgumentsBundle;
import edu.claflin.finder.algo.clustering.struct.infomap_struct.InfomapImplementation;
import edu.claflin.finder.log.LogLevel;
import edu.claflin.finder.logic.Graph;


/**
 * InfomapImplementation algorithm implemented using Mapping Higher-Order Network Flows in Memory
 * and Multilayer Networks with InfomapImplementation by Daniel Edler, Ludvig Bohlin and Martin Rosvall.
 *
 * There are somewhat detailed comments and descriptions in:
 * 	edu.claflin.finder.algo.clustering.struct.louvain_struct.LouvainAlgorithm.java
 *
 */
public class Infomap extends ClusteringAlgorithm
{

    public Infomap(ArgumentsBundle args)
    {
        super(args);

        if (getLogger() != null)
        {
            getLogger().logInfo(LogLevel.DEBUG, "Community detection with the InfoMap algorithm initialized..");
        }

    }

    @Override
    public String toString()
    {
        return "InfoMap Algorithm";
    }

    /**
     * Performs community detection using the InfoMap algorithm
     *
     * @param graph the Graph on which community detection will be performed
     * @return the list of Graphs representing the clustering with the lowest
     * average bit length measured by the MapEquation
     */
    @Override
    public ArrayList<Graph> process(Graph graph)
    {
        if (getLogger() != null)
        {
            getLogger().logAlgo(LogLevel.NORMAL,
                    "InfoMap: Searching Graph: " + graph.getName() + "\nRunning Algorithm");
        }

        if (graph.getNodeCount() <= 1)
        {
            return new ArrayList<Graph>();
        }

        InfomapImplementation infomapAlgorithm = new InfomapImplementation(graph);

        if (getLogger() != null)
        {
            getLogger().logAlgo(LogLevel.NORMAL,
                    "InfoMap: Algorithm done. Getting Clustering with Minimum Bit Length");
        }

        Communities communities = new Communities(infomapAlgorithm.cluster(), graph, isWeighted());

        ArrayList<Graph> result = new ArrayList<>();

        if (communities != null)
        {
            result = this.buildCommunityGraphs(communities.getList(), graph, "InfoMap Algorithm");
        }

        return cull(result);
    }

}