package de.visone.nlpext.util;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import au.com.bytecode.opencsv.CSVReader;
import de.visone.ext.nlp.TextNetworkUtil;

/**
 * This class can be used to read a csv file (or many files) into a HashMap that
 * maps Strings to double values and to process it (or lists of HashMaps).
 * 
 * @author <a href="mailto:endele@inf.uni-konstanz.de">Simon Endele</a>
 */
public class HashMapReader {
	private static final char TEXT_FRAME = '"';
	private static final char CELL_SEPARATOR = ',';

	private HashMapReader() {
	}

	/** Returns */
	public static LinkedHashMap<String, Double> readFile(final File file,
			final String centralityName) throws IOException {
		return readFile(new FileReader(file), centralityName);
	}

	public static LinkedHashMap<String, Double> readFile(final String fileName,
			final String centralityName) throws IOException {
		return readFile(new FileReader(fileName), centralityName);
	}

	public static LinkedHashMap<String, Double> readFile(
			final FileReader fileReader, final String centralityName)
			throws IOException {
		final BufferedReader bufferedReader = new BufferedReader(fileReader);
		final LinkedHashMap<String, Double> hashMap = new LinkedHashMap<String, Double>();
		/*
		 * while (reader.ready()) { String line = reader.readLine(); String[]
		 * words = line.trim().split("[ \t;]"); if (words.length!=2) {
		 * System.out.println("Splits: "+words.length+", line: "+line);
		 * continue; } hashMap.put(words[0], new Double(words[1])); }
		 */
		final CSVReader reader = new CSVReader(bufferedReader, CELL_SEPARATOR,
				TEXT_FRAME);
		int wordAttrIndex = -1;
		int centrAttrIndex = -1;
		String[] attrLine = reader.readNext();
		// System.out.println(Arrays.toString(attrLine));
		// System.exit(0);
		for (int i = 0; i < attrLine.length; i++) {
			if (attrLine[i].equals(TextNetworkUtil.ATTR_NAME_WORD)) {
				wordAttrIndex = i;
			}
			if (attrLine[i].equals(centralityName)) {
				centrAttrIndex = i;
			}
		}
		if (wordAttrIndex == -1 || centrAttrIndex == -1) {
			reader.close();
			return hashMap;
		}
		while ((attrLine = reader.readNext()) != null) {
			hashMap.put(attrLine[wordAttrIndex], new Double(
					attrLine[centrAttrIndex]));
			// System.out.println();
		}
		reader.close();
		return hashMap;
	}

	public static List<LinkedHashMap<String, Double>> readFiles(
			final File[] files, final String centralityName) throws IOException {
		final FileReader[] fileReaders = new FileReader[files.length];
		for (int i = 0; i < files.length; i++) {
			fileReaders[i] = new FileReader(files[i]);
		}
		return readFiles(fileReaders, centralityName);
	}

	public static List<LinkedHashMap<String, Double>> readFiles(
			final String[] fileNames, final String centralityName)
			throws IOException {
		final FileReader[] fileReaders = new FileReader[fileNames.length];
		for (int i = 0; i < fileNames.length; i++) {
			fileReaders[i] = new FileReader(fileNames[i]);
		}
		return readFiles(fileReaders, centralityName);
	}

	public static List<LinkedHashMap<String, Double>> readFiles(
			final FileReader[] fileReaders, final String centralityName)
			throws IOException {
		final List<LinkedHashMap<String, Double>> list = new LinkedList<LinkedHashMap<String, Double>>();
		for (final FileReader fileReader : fileReaders) {
			final LinkedHashMap<String, Double> hashMap = readFile(fileReader,
					centralityName);
			list.add(hashMap);
		}
		return list;
	}

	public static List<Double> extract(
			final List<? extends Map<String, Double>> mapList, final String key) {
		final List<Double> list = new LinkedList<Double>();
		for (final Map<String, Double> map : mapList) {
			list.add(map.get(key));
		}
		return list;
	}

	public static double[] extractAsArray(
			final List<? extends Map<String, Double>> mapList, final String key) {
		return toArray(extract(mapList, key));
	}

	public static double[] toArray(final List<Double> list) {
		final double[] array = new double[list.size()];
		final Iterator<Double> iter = list.iterator();
		for (int i = 0; i < list.size(); i++) {
			final Double d = iter.next();
			array[i] = d == null ? 0.0 : d.doubleValue();
		}
		return array;
	}

	public static double max(final List<Double> list) {
		double max = -Double.MAX_VALUE;
		final Iterator<Double> iter = list.iterator();
		for (int i = 0; i < list.size(); i++) {
			final Double dou = iter.next();
			final double d = dou == null ? 0.0 : dou.doubleValue();
			max = Math.max(d, max);
		}
		return max;
	}

	public static double max(final List<? extends Map<String, Double>> mapList,
			final String... keys) {
		double max = -Double.MAX_VALUE;
		for (final String key : keys) {
			final double d = max(extract(mapList, key));
			max = Math.max(d, max);
		}
		return max;
	}

	public static <K, V> TreeSet<K> getAllKeys(
			final List<? extends Map<K, V>> mapList) {
		final TreeSet<K> set = new TreeSet<K>();
		for (final Map<K, V> map : mapList) {
			set.addAll(map.keySet());
		}
		return set;
	}

	/*
	 * public static void main(String[] args) throws IOException {
	 * LinkedHashMap<String, Double> hm =
	 * readFile("/net/algo/data/9-11/betweenness/01_centr.txt");
	 * System.out.println(hm.get(args[0])); }
	 */
}