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.louvain_struct.LouvainAlgorithm;
import edu.claflin.finder.log.LogLevel;
import edu.claflin.finder.logic.Graph;

/**
 * Louvain algorithm implemented using the brief description by Mark Newman on pages 511-512 of
 * "Networks Second Edition".
 * 
 * There are somewhat detailed comments and descriptions in:
 * 	edu.claflin.finder.algo.clustering.struct.louvain_struct.LouvainAlgorithm.java
 * 
 * @author Samuel Perez
 *
 */
public class Louvain extends ClusteringAlgorithm
{

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

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

	}

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

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

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

		LouvainAlgorithm louvain = new LouvainAlgorithm(graph);

		if (getLogger() != null)
		{
			getLogger().logAlgo(LogLevel.NORMAL,
					"Louvain: Algorithm done. Getting Clustering with Maximum Modularity");
		}
		
		Communities communities = new Communities(louvain.getCommunities(), graph, isWeighted());
		
		ArrayList<Graph> result = new ArrayList<>();

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

		return cull(result);
	}

}