package csv;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import util.Pair;

public class CSV2OMLTabularData {
	
	private static StringBuilder bufferCells;
	private static StringBuilder bufferRows;

	public static void generateOML(String tableName, String csvPath, String outputPath, String version, String iri,
			Pair<String,String> uses, Pair<String,String> ext) throws FileNotFoundException, IOException {
		CSVParser parser;

		String header = generateHeader(iri, uses, ext);
		String prefixTable = ext.getSnd();
		
		StringBuilder aux = new StringBuilder();
		parser = new CSVParser(new FileReader(csvPath), CSVFormat.DEFAULT);
		List<CSVRecord> list = parser.getRecords();
		String table = "";
		String headerRow = "";
		StringBuilder rows = new StringBuilder();
		StringBuilder cells = new StringBuilder();

		table = generateTable(prefixTable, tableName, prefixTable, list, version, csvPath);

		headerRow = generateRow(aux, list.get(0), prefixTable, tableName, true);
		
		StringBuilder content = new StringBuilder();
		content.append(header);
		content.append(table);
		content.append(headerRow);
		
		FileWriter fw = new FileWriter(new File(outputPath));
		fw.write(content.toString());
		fw.flush();
		// generating the rows
		for (CSVRecord record : list) {
			
			if (record.getRecordNumber() > 1) {
				rows.append(generateRow(aux, record, prefixTable, tableName, false));
				
				if (rows.capacity() > 200000000) {
					fw.append(rows.toString());
					fw.flush();
					rows.delete(0, rows.length());
				}
			}

		}
		fw.append(rows.toString());
		fw.flush();
		rows.delete(0, rows.length());
		// generating the cells
		for (CSVRecord record : list) {
			if (cells.capacity() > 200000000) {
				fw.append(cells.toString());
				fw.flush();
				cells.delete(0, cells.length());
			}
			cells.append(generateCells(aux, record, prefixTable, tableName));
			
		}
		
		fw.append(cells.toString());
		fw.append("\n}\n");
		fw.flush();
		fw.close();
		parser.close();
		
	}

	private static String generateHeader(String iri, Pair<String, String> uses, Pair<String, String> ext) {
		StringBuilder sb = new StringBuilder();
		sb.append("description " + iri + " as csv {\n");
		sb.append("\tuses " + uses.getFst() + " as " + uses.getSnd() + "\n");
		sb.append("\textends " + ext.getFst() + " as " + ext.getSnd() + "\n\n");
		return sb.toString();
	}

	private static String generateTable(String prefix, String tableName, String tableName2, List<CSVRecord> list, String version, String cvsPath) {
		StringBuilder sb = new StringBuilder();
		StringBuilder rowList = new StringBuilder();
		StringBuilder cellList = new StringBuilder();
		sb.append("\tref ci "+ prefix + ":" + tableName + " : tabular:TabularData [\n");

		for (CSVRecord record : list) {
			rowList.append("\t\ttabular:hasRows " + tableName + "-row-" + (record.getRecordNumber() - 1) + "\n");
//			for (int i = 0; i < record.size(); i++) {
//				cellList.append("\t\ttabular:hasCells " + tableName + "-cell-" + (record.getRecordNumber() - 1) + "" + i
//						+ "\n");
//			}
		}
		sb.append(cellList);
		sb.append(rowList);
		sb.append("\t]\n");
		sb.append("\n");
		return sb.toString();
	}

	private static String generateCells(StringBuilder sb, CSVRecord record, String prefix, String tableName) {
		sb.delete(0, sb.length());
		for (int i = 0; i < record.size(); i++) {
			
			sb.append("\tci " + tableName + "-cell-" + (record.getRecordNumber() - 1) + "" + i + " : tabular:Cell [\n");
			sb.append("\t\ttabular:hasRowPosition " + (record.getRecordNumber() - 1) + " ");
			sb.append("\t\ttabular:hasColumnPosition " + i + " ");
			sb.append("\t\ttabular:holdsContent \"" + record.get(i) + "\" ");
			sb.append("\t\ttabular:isCellOfTabularData " + prefix + ":" + tableName + " ");
			sb.append("\t\ttabular:isInCollection " + tableName + "-row-" + (record.getRecordNumber() - 1) + " ");
			sb.append("\n\t]\n");
		}

		return sb.toString();
	}

	private static String generateRow(StringBuilder sb, CSVRecord record, String prefix, String tableName, boolean headerRow) {
		sb.delete(0, sb.length());
		sb.append("\tci " + tableName + "-row-" + (record.getRecordNumber() - 1) + " : tabular:"
				+ (headerRow ? "HeaderRow" : "Row") + " [\n");
		if (!headerRow) {
			//sb.append("\t\ttabular:hasHeadingModifier \"no\"\n");
			sb.append("\t\ttabular:hasHeadingModifier \"no\" ");
		}
		//sb.append("\t\ttabular:hasRowId " + (record.getRecordNumber() - 1) + "\n");
		//sb.append("\t\ttabular:isRowOfTabularData "+ prefix + ":" + tableName + "\n");
		sb.append("\t\ttabular:hasRowId " + (record.getRecordNumber() - 1) + " ");
		sb.append("\t\ttabular:isRowOfTabularData "+ prefix + ":" + tableName + " ");

		for (int i = 0; i < record.size(); i++) {
			//sb.append("\t\ttabular:hasCell " + tableName + "-cell-" + (record.getRecordNumber() - 1) + i + "\n");
			sb.append("\t\ttabular:hasCell " + tableName + "-cell-" + (record.getRecordNumber() - 1) + i + " ");
		}
		sb.append("\n\t]\n");
		return sb.toString();
	}

	public static void main(String[] args) throws FileNotFoundException, IOException {
		generateOML("drivetrain-sensor-data-v1", "src/main/resources/csv/sensor.csv", "target/sensor.oml", "v1",
				"<http://ua.com.be/sdo2l/description/drivetrain/artifacts/sensor#>", 
				new Pair<String, String>("<http://ua.com.be/sdo2l/vocabulary/base/tabular#>", "tabular"),
				new Pair<String, String>("<http://ua.com.be/sdo2l/description/drivetrain/artifacts/artifacts#>", "art"));
		generateOML("torque-profile-v1", "src/main/resources/csv/profile.csv", "target/profile.oml", "v1",
				"<http://ua.com.be/sdo2l/description/drivetrain/artifacts/profile#>", 
				new Pair<String, String>("<http://ua.com.be/sdo2l/vocabulary/base/tabular#>", "tabular"),
				new Pair<String, String>("<http://ua.com.be/sdo2l/description/drivetrain/artifacts/artifacts#>", "art")
				);
		generateOML("coupling-sensor-data-v1", "src/main/resources/csv/coupling.csv", "target/coupling.oml", "v1",
				"<http://ua.com.be/sdo2l/description/drivetrain/artifacts/coupling#>", 
				new Pair<String, String>("<http://ua.com.be/sdo2l/vocabulary/base/tabular#>", "tabular"),
				new Pair<String, String>("<http://ua.com.be/sdo2l/description/drivetrain/artifacts/artifacts#>", "art"));

		
		
//		generateOML("rotation-sensor-data-v1", "src/main/resources/csv/rotation.csv", "target/rotation.oml", "v1",
//				"<http://ua.com.be/sdo2l/description/drivetrain/artifacts/rotation#>", 
//				new Pair<String, String>("<http://ua.com.be/sdo2l/vocabulary/base/tabular#>", "tabular"),
//				new Pair<String, String>("<http://ua.com.be/sdo2l/description/drivetrain/artifacts/artifacts#>", "art"));
		

		
	}

}
