/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package it.cnr.iasi.giant.thread;

import it.cnr.iasi.giant.Main;
import it.cnr.iasi.giant.action.RunClusteringAction;
import it.cnr.iasi.giant.algorithm.clustering.NormalizedSpectralClustering;
import it.cnr.iasi.giant.algorithm.clustering.UnnormalizedSpectralClustering;
import it.cnr.iasi.giant.algorithm.distance.GraphUtil;
import it.cnr.iasi.giant.frame.SpectralInitFrame;
import it.cnr.iasi.giant.io.IOWriter;
import it.cnr.iasi.giant.util.Helper;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import net.sf.javaml.clustering.Clusterer;
import net.sf.javaml.core.Dataset;
import net.sf.javaml.core.Instance;
import net.sf.javaml.tools.data.FileHandler;

/**
 *
 * @author Fabio Cumbo
 * @info GIANT
 * @version v1.0
 * @organization IASI-CNR : Istituto di Analisi dei Sistemi ed Informatica 
 *                  "Antonio Ruberti" - Consiglio Nazionale delle Ricerche
 * 
 */
public class SpectralClusteringThread extends Thread {
    
    private boolean normalized = false;
    private int clusters = 4;
    private String dist;
    
    public SpectralClusteringThread() {}
    
    public SpectralClusteringThread(boolean norm, String d) {
        normalized = norm;
        dist = d;
    }
    
    public SpectralClusteringThread(int k, String d) {
        clusters = k;
        dist = d;
    }
    
    public SpectralClusteringThread(boolean norm, int k, String d) {
        normalized = norm;
        clusters = k;
        dist = d;
        
    }
    
    @Override
    public void run() {
        try {
            IOWriter writer = new IOWriter();
            String tmpAdjFilePath = writer.writeTmpAdjMatrixFile(NetworkLoaderThread.getAdjMatrix());
            Dataset data = FileHandler.loadDataset(new File(tmpAdjFilePath), Main.getGiantAdapter().getCyApplicationManager().getCurrentNetwork().getNodeList().size()-1, " ");
            Clusterer spectral = null;
            
            if (dist.equals("SP")) {
                GraphUtil graph = new GraphUtil(NetworkLoaderThread.getDegreeMap().keySet().size(), NetworkLoaderThread.getAdjMatrix());
                    if (normalized)
                        spectral = new NormalizedSpectralClustering(clusters, graph, "SP");
                    else
                        spectral = new UnnormalizedSpectralClustering(clusters, graph, "SP");
            }
            else if (dist.equals("HAMMING")) {
                if (normalized)
                        spectral = new NormalizedSpectralClustering(clusters, null, "HAMMING");
                    else
                        spectral = new UnnormalizedSpectralClustering(clusters, null, "HAMMING");
            }
            
            Dataset[] result = spectral.cluster(data);
                        
            HashMap<Integer, ArrayList<String>> clustersResult = new HashMap<Integer, ArrayList<String>>();
            ArrayList<String> list = new ArrayList<String>(NetworkLoaderThread.getDegreeMap().keySet());
                        
            int lb = Integer.MAX_VALUE;
            for (int i=0; i<result.length; i++) {
                Dataset ds = result[i];
                Instance inst = ds.get(0);
                if (lb > inst.getID())
                    lb = inst.getID();
            }
            int ub = lb + NetworkLoaderThread.getDegreeMap().keySet().size() -1;
                        
            HashMap<Integer, Integer> newMap = RunClusteringAction.getNewMap(ub, lb);

            for (int i=0; i<result.length; i++) {
                Dataset ds = result[i];
                ArrayList<String> tmp = new ArrayList<String>();
                for (int j=0; j<ds.size(); j++) {
                    Instance inst = ds.get(j);
                    System.err.print(inst.getID() + " ");          
                        tmp.add(list.get(newMap.get(inst.getID())));
                }
                clustersResult.put(i, tmp);
                System.err.println();
            }
                        
            String filePath = writer.writeTmpClusterFile(clustersResult);

            if (!clustersResult.isEmpty() && !filePath.equals("NULL")) {
                ClusterLoaderThread.setClusterFileName("SPECTRAL-CLUSTERING-POWERED");
                ClusterLoaderThread.setClusterFilePath(filePath);
                ClusterLoaderThread.setClusters(clustersResult);
                            
                SpectralInitFrame.appendInConsole("SPECTRAL CLUSTERING: completed at " + Helper.getCurrentTime());
                SpectralInitFrame.appendInConsole("CLUSTERS: " + clustersResult.size());
                for (int t=0; t<clustersResult.size(); t++)
                    SpectralInitFrame.appendInConsole("cluster " + (t+1) + "  -  size: " + clustersResult.get(t).size());
                SpectralInitFrame.appendInConsole("---------------------------------------------------------");
            }
            else {
                SpectralInitFrame.appendInConsole("INTERNAL ERROR: please retry...");
                SpectralInitFrame.appendInConsole("---------------------------------------------------------");
            }
            
        } catch (IOException e) {
            SpectralInitFrame.appendInConsole("INTERNAL ERROR: please retry...");
            SpectralInitFrame.appendInConsole("---------------------------------------------------------");
        }
    }
    
}
