import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;

public class TestSuiteStructureGenerator {

	public static Properties config = new Properties();
	public static Properties references = new Properties();
	private ArrayList<File> files = new ArrayList<File>();
	private HashMap<String, ArrayList<ClauseEntry>> clauseMapPositive = new HashMap<String, ArrayList<ClauseEntry>>();
	private HashMap<String, ArrayList<ClauseEntry>> clauseMapNegative = new HashMap<String, ArrayList<ClauseEntry>>();

	// -----------------------------------------------------------------------------------------------

	public TestSuiteStructureGenerator() {
	}

	// -----------------------------------------------------------------------------------------------

	public void run() {
		System.out.println("STF475 Tools: Test Suite Structure Tables Generator v0.1");
		try {
			FileUtils.loadConfig(config);
			FileUtils.loadReferences(references);
		} catch (IOException e) {
			System.err
			.println("[ERROR] Cannot load config file or config file is incomplete.");
			return;
		}

		List<Clause> myList = new ArrayList<Clause>();
		Iterator<Object> it = references.keySet().iterator();
		System.out.println("----");
		while (it.hasNext()) {
			Object value = it.next();
			if (value instanceof String) {
				myList.add(new Clause((String) value));
			}
		}

		Collections.sort(myList);
		try {

			String atsPath = config.get("ATSPath").toString();
			System.out.println("Gathering files...");
			FileUtils.visitAllFiles(new File(atsPath), files);

			System.out.println("Processing files...");
			for (int i=0; i < files.size(); i++) {
				//			File tempFile = new File(config.get("TempPath") + "/" + files.get(i).getName());
				File tempFile = files.get(i); //new File(config.get("TempPath") + "/" + files.get(i).getName());
				//			try {
				//				FileUtils.copyFile(files.get(i), tempFile);
				//			} catch (IOException e) {
				//				e.printStackTrace();
				//			}
				T3Purpose purpose = FileUtils.extractPurpose(tempFile);
				T3ExpectedOutput expected = FileUtils.extractExpectedOutput(tempFile);
				//			System.out.println(purpose.getClauseStructured());

				//			System.out.println("processing " + files.get(i).getName());
				Clause clauseStructured = purpose.getClauseStructured();
				if (clauseStructured == null) {
					throw new IOException("Error scanning structured clause for file "+tempFile+" purpose: "+ purpose.toString());
				}
				if (files.get(i).getName().toLowerCase().startsWith("neg")) {
					ArrayList<ClauseEntry> clauseEntries = clauseMapNegative.get(clauseStructured.toString());
					if (clauseEntries == null)
						clauseEntries = new ArrayList<ClauseEntry>();

					ClauseEntry clauseEntry = new ClauseEntry();
					clauseEntry.setFile(tempFile);
					clauseEntry.setPurpose(purpose);
					clauseEntry.setExpected(expected);
					clauseEntries.add(clauseEntry);
					clauseMapNegative.put(clauseStructured.toString(), clauseEntries);
				} else {
					ArrayList<ClauseEntry> clauseEntries = clauseMapPositive.get(clauseStructured.toString());
					if (clauseEntries == null)
						clauseEntries = new ArrayList<ClauseEntry>();

					ClauseEntry clauseEntry = new ClauseEntry();
					clauseEntry.setFile(tempFile);
					clauseEntry.setPurpose(purpose);
					clauseEntry.setExpected(expected);
					clauseEntries.add(clauseEntry);
					clauseMapPositive.put(clauseStructured.toString(), clauseEntries);
				}
			}


			String tssFileHead = FileUtils.loadFileToString(new File("resources/tss-file-head.html"));
			String tssFileFooter = FileUtils.loadFileToString(new File("resources/tss-file-foot.html"));
			String tssSectionHead = FileUtils.loadFileToString(new File("resources/tss-section-head.html"));
			String tssSectionFoot = FileUtils.loadFileToString(new File("resources/tss-section-foot.html"));

			StringBuffer result = new StringBuffer();
			result.append(tssFileHead);

			// positive tests
			createTable(myList, "B.1", "Test suite structure, positive tests", tssSectionHead, tssSectionFoot, clauseMapPositive, result);

			// negative tests
			createTable(myList, "B.2", "Test suite structure, negative tests", tssSectionHead, tssSectionFoot, clauseMapNegative, result);

			result.append(tssFileFooter);
			FileUtils.saveStringToFile(new File(config.getProperty("DeliverableATSPath")+"/stf475-tss.html"), result.toString());
		} catch (IOException e) {
			e.printStackTrace();
		}

		System.out.println("done.");
	}

	private void createTable(List<Clause> myList, String tableNumber, String tableDescription, String tssSectionHead,
			String tssSectionFoot, HashMap<String, ArrayList<ClauseEntry>> clauseMap, StringBuffer result) {
		result.append(createSectionHead(tssSectionHead, tableNumber, tableDescription));
		TSSTable table = new TSSTable();

		TSSRow row = null;
		for (int i=0; i < myList.size(); i++) {
			Clause clause = myList.get(i);

			ArrayList<ClauseEntry> clauseEntries = null;
			if (!clause.toString().contains(".")) { // top level
				if (row != null) {
					table.addRow(row);
					row = null;
				}

				clauseEntries = clauseMap.get(clause.toString());

				row = new TSSRow();
				row.setChapter(clause.toString() + " " + references.getProperty(clause.toString()));

				if ((clauseEntries != null) && (clauseEntries.size() > 0)) {
					TSSClause tssClause = new TSSClause();
					tssClause.setClauseName("Top level");
					for (int j=0; j < clauseEntries.size(); j++) {
						ClauseEntry entry = clauseEntries.get(j);
						tssClause.addTestCase(entry.getFile().getName().replaceAll("\\.ttcn", ""));
					}

					row.addClause(tssClause);
				}
			} else {
				clauseEntries = clauseMap.get(clause.toString());

				if ((clauseEntries != null) && (clauseEntries.size() > 0)) {
					TSSClause tssClause = new TSSClause();
					tssClause.setClauseName(clause.toString() + " " + references.getProperty(clause.toString()));
					for (int j=0; j < clauseEntries.size(); j++) {
						ClauseEntry entry = clauseEntries.get(j);
						tssClause.addTestCase(entry.getFile().getName().replaceAll("\\.ttcn", ""));
					}
					row.addClause(tssClause);
				}					
			}
		}
		result.append(table.toHtml());
		result.append(tssSectionFoot);
	}

	// -----------------------------------------------------------------------------------------------

	//	private String createTableRow(String tableRow, int number, String purpose, String clause, String status, String tpRef) throws IOException {
	//		String icsTableRow = tableRow.replaceAll("\\{\\{NUMBER\\}\\}", Integer.toString(number));
	//		icsTableRow = icsTableRow.replaceAll("\\{\\{PURPOSE\\}\\}", purpose);
	//		icsTableRow = icsTableRow.replaceAll("\\{\\{CLAUSE\\}\\}", clause);
	//		icsTableRow = icsTableRow.replaceAll("\\{\\{STATUS\\}\\}", status);
	//		icsTableRow = icsTableRow.replaceAll("\\{\\{TCTPREF\\}\\}", tpRef);
	//		
	//		return icsTableRow;
	//		
	//	}

	private String createSectionHead(String sectionHead, String tableNumber, String tableDescription) {
		String newSectionHead = sectionHead.replaceAll("\\{\\{TABLENUMBER\\}\\}", tableNumber);
		newSectionHead = newSectionHead.replaceAll("\\{\\{TABLEDESCRIPTION\\}\\}", tableDescription);
		return newSectionHead;
	}

	// -----------------------------------------------------------------------------------------------

	public static void main(String[] args) {
		new TestSuiteStructureGenerator().run();
	}

}
