/*
  This file is part of the BJP package.

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

  BJP 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 Lesser General Public
  License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with BJP package.  If not, see <http://www.gnu.org/licenses/>.
 */
package util.files;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Collection;

import rep.UndirectedGraph;
import util.math.JGraphtUtils;

/**
 * Allows to read a graph from data. It assumes that the representation of the
 * graph is the same that returns the toString() method of the
 * graphs.UndirectedGraph class. 
 * 
 * @author fschluter
 * 
 */
public class UndirectedGraphParser {

	/**
	 * @param datasetName
	 * @param numberOfNodes
	 * @return
	 */
	public static UndirectedGraph readTrueGraph(String datasetName, int numberOfNodes) {
		UndirectedGraph trueGraph = new UndirectedGraph(numberOfNodes);
		try {
			BufferedReader br;
			br = new BufferedReader(new FileReader(datasetName + ".graph"));
			String line = br.readLine();
			int row = 0;
			while (line != null) {
				String[] splitedLine = line.split(" ");
				for (int i = 0; i < splitedLine.length; i++) {
					trueGraph.adjMatrix[row][i] = splitedLine[i].equals("1") ? true : false;
				}
				line = br.readLine();
				++row;
			}
			br.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return trueGraph;
	}
	
	/**
	 * @param datasetName
	 * @param numberOfNodes
	 * @return
	 * @throws IOException 
	 */
	public static UndirectedGraph readTrueGraph(String datasetName) throws IOException {
			BufferedReader br;
			br = new BufferedReader(new FileReader(datasetName));
			String line = br.readLine();
			int n = line.split(" ").length;
			UndirectedGraph trueGraph = new UndirectedGraph(n);
			int row = 0;
			while (line != null) {
				String[] splitedLine = line.split(" ");
				for (int i = 0; i < splitedLine.length; i++) {
					if(splitedLine[i].equals("1")) 
						trueGraph.addEdge(row,i);
				}
				line = br.readLine();
				++row;
			}
			br.close();
			return trueGraph;
	}
	
	public static void writeGraphInAdjacencyMatrixFormat(UndirectedGraph graph, String outputFile) {
		try {
			/* Create file */
			FileWriter fstream = new FileWriter(outputFile, false);
			BufferedWriter out = new BufferedWriter(fstream);
			out.write(graph.toString());
			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}
	
	public static void writeGraphInLibraFormat(UndirectedGraph graph, int domainSize, String outputFile) {
		try {
			/* Create file */
			FileWriter fstream = new FileWriter(outputFile, false);
			BufferedWriter out = new BufferedWriter(fstream);
			String fileContent = "";
			out.write(fileContent);
			int n = graph.getNumberOfNodes();
			
			for (int i = 0; i < n; ++i) {
				/* In this version, only binary domains are considered */
				fileContent += domainSize + ",";
			}
			/* Removing last comma */
			fileContent = fileContent
					.substring(0, fileContent.length() - 1);
			fileContent += "\n";
			fileContent += "MN { \n";
			out.write(fileContent);
			fileContent = "";
			
			Collection<java.util.Set<String>> cliques = JGraphtUtils.getAllMaximalCliques(graph);
			for (java.util.Set<String> clique : cliques) {
				int cliqueSize = clique.size();
				int[] vars = new int[cliqueSize];
				int[] aux = new int[cliqueSize];
				int[] domains = new int[cliqueSize];
				int x = 0;
				for (String var : clique) {
					vars[x] = new Integer(var);
					domains[x] = domainSize-1;
					x++;
				}

				fileContent = getPermutations(aux, domains, 0, vars);
				out.write(fileContent);

			}

			fileContent = "} \n";
			out.write(fileContent);

			out.close();
		} catch (Exception e) {// Catch exception if any
			System.err.println("Error: " + e.getMessage());
		}
	}

	private static String getPermutations(int[] n, int[] Nr, int idx,
			int[] vars) {
		String allPermutations = "";
		/* stop condition for the recursion [base clause] */
		if (idx == n.length) {
			String assignment = "0.000 "; 
			for (int i = 0; i < n.length; ++i) {
				assignment += "+v" + vars[i] + "_" + n[i] + " ";
			}
			assignment += "\n";
			return assignment;
		}
		for (int i = 0; i <= Nr[idx]; i++) {
			n[idx] = i;
			allPermutations += getPermutations(n, Nr, idx + 1, vars); // recursive
			// invokation,
			// for
			// next
			// elements
		}
		return allPermutations;
	}

}
