package eu.dnetlib.data;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Iterator;
import java.util.Map;

import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVStrategy;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;

import com.google.common.base.Function;
import com.google.common.collect.Maps;
import com.google.gson.Gson;
import com.google.gson.stream.JsonWriter;

public class CsvToJsonParser {
	
	private CSVParser parser;
	
	private Map<String, String> xPaths = Maps.newHashMap();
	
	private static final File openaireMdFormatFile = new File("src/main/eu/dnetlib/data/xml/openaireMetadataFormat.xml").getAbsoluteFile();
	
	public CsvToJsonParser() throws DocumentException {
		Document openaireMdFormat = new SAXReader().read(openaireMdFormatFile);
		
		for(Object fieldNode : openaireMdFormat.selectNodes("//LAYOUT[@name='index']/FIELDS/FIELD") ) {
			Element e = (Element) fieldNode;
			String xpath = e.attributeValue("xpath") != null ? e.attributeValue("xpath") : "//*[local-name()='" + e.attributeValue("name") + "']";  
			xPaths.put(e.attributeValue("name"), xpath); 
		}
	}
	
	public String generateJson(final Document document) {
		
		
		Map<String, String> values = Maps.transformValues(xPaths, new Function<String, String>() {
			@Override
			public String apply(String xpath) {
				String value = document.valueOf(xpath);
				System.out.println(xpath + " - " + value);
				return value;

			}});
		System.out.println(document.asXML());
		//TypeToken<Map<String, String>> mapType = new TypeToken<Map<String, String>>() {};
		StringWriter writer = new StringWriter();
		new Gson().toJson(values, Map.class, new JsonWriter(writer));
		
		return writer.toString();
	}

	public Iterator<Document> streamParser(String inFile) throws FileNotFoundException {
		
		parser = new CSVParser(new FileReader(new File(inFile)), new CSVStrategy('\n', '"', '#'));		
		final SAXReader reader = new SAXReader();
		
		return new Iterator<Document>() {

			String[] line = {""};
			
			@Override public boolean hasNext() {
				try {
					line = parser.getLine();
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
				return line != null && !line[0].isEmpty();
			}

			@Override public Document next() {
				String record = "";
				try {

					record = StringUtils.concatenate(line) + "";
					
					return reader.read(new StringReader(record));
				} catch (DocumentException e) {
					throw new RuntimeException("record:\n" + record, e);
				}
			}

			@Override public void remove() {}
		};
	}
	
}
