package de.ugoe.cs.swe.exercises.exercisesheet;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.Scanner;
import java.util.regex.Matcher;

import org.eclipse.jface.util.Util;
import org.eclipse.swt.widgets.Shell;

import de.ugoe.cs.swe.exercises.exercise.Exercise;
import de.ugoe.cs.swe.exercises.exercise.ExerciseSVN;
import de.ugoe.cs.swe.exercises.lectureevent.LectureEvent;
import de.ugoe.cs.swe.exercises.lecturer.Lecturer;
import de.ugoe.cs.swe.exercises.misc.FileUtils;
import de.ugoe.cs.swe.exercises.svn.SettingsDialog;

public class PdfGenerator {
	
	public static void generatePdf(ExerciseSheet exercisesheet, String path,
			boolean copyFile, boolean makeExerciseInsteadOfSolution) {
		ExerciseSVN.SVNCheckout(exercisesheet.returnMaxRevision());
		if (!path.endsWith(".pdf"))
			path += ".pdf";

		SettingsDialog settings = new SettingsDialog(new Shell());
		ArrayList<String> cmdList = new ArrayList<String>();

		String cmd = "\"" + settings.getmyPDFLatexPath() + "\""
				+ " -halt-on-error -output-directory=\"";
		try {
			File latexFile = File.createTempFile("exercise", ".tex");

			cmdList.add(settings.getmyPDFLatexPath());
			cmdList.add("-halt-on-error");
			cmdList.add("-output-directory=" + latexFile.getParent());
			cmdList.add(latexFile.getAbsolutePath());

			cmd += latexFile.getParent() + "\" \""
					+ latexFile.getAbsolutePath() + "\"";

			String filename = ExerciseSVN.SVNpath + "/template-";

			if (exercisesheet.isExamination()) {
				filename += "klausur";
			} else {
				filename += "uebung";
			}

			filename += ".tex";

			// read template file
			File templateFile = new File(filename);
			String template = "";
			FileInputStream fstream = new FileInputStream(templateFile);
			BufferedReader dstream = new BufferedReader(new InputStreamReader(
					fstream, "UTF8"));
			String line;
			while ((line = dstream.readLine()) != null) {
				template += line + "\n";
			}
			dstream.close();

			// initialize strings			
			LectureEvent event = exercisesheet.getLectureEvent();
			ArrayList<Lecturer> lecturers = event.getLecturers();
			String lecturersString = "";
			boolean firstRun = true;
			
			// build lecturer placeholder string
			for (Lecturer lecturer : lecturers) {
				if (!firstRun)
					lecturersString += ", ";
				lecturersString += lecturer.toString().trim();
				firstRun = false;
			}
			if (lecturersString == "")
				lecturersString = "!NO LECTURERS FOUND!";

			// concatenate exercises or solution to one content
			ArrayList<Exercise> exercises = exercisesheet.getExercises();
			String exercisesString = "";
			for (Exercise exercise : exercises) {
				String text;
				if (makeExerciseInsteadOfSolution)
					text = exercise.getExerciseText(exercisesheet
							.returnMaxRevision());
				else
					text = exercise.getSolution(exercisesheet
							.returnMaxRevision());
				exercisesString += "\n\\section{" + exercise.getTitle() + "}\n"
						+ text;
			}

			// declare execercise to be an examination or exercise
			// TODO: dirty
			String examorunit = "";

			if (exercisesheet.isExamination()) {
				examorunit = "Prüfung";
			} else {
				examorunit = "Übungszettel";
			}

			// replace placeholders in generated text file
			String templatePath = ExerciseSVN.SVNpath;
			templatePath = templatePath.replace('\\','/');

			long dueDateTimeStamp = ((long)exercisesheet.getDueDate()) * 1000;
			Calendar dueDate = new GregorianCalendar();
			dueDate.setTimeInMillis(dueDateTimeStamp);
			DateFormat dateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM, Locale.GERMANY);
			String dueDateString = dateFormat.format(dueDate.getTime());
			
			template = template.replaceAll("(\\W)LECTURE(\\W)", "$1"
					+ Matcher.quoteReplacement(event.toString()) + "$2");
			template = template.replaceAll("(\\W)LECTURERS(\\W)", "$1"
					+ Matcher.quoteReplacement(lecturersString) + "$2");
			template = template.replaceAll("(\\W)EXAMORUNIT(\\W)", "$1"
					+ Matcher.quoteReplacement(examorunit) + "$2");
			template = template.replaceAll("(\\W)SHEETNUMBER(\\W)", "$1"
					+ Matcher.quoteReplacement(String.valueOf(exercisesheet
							.getNumber())) + "$2");
			template = template.replaceAll("(\\W)EXERCISES(\\W)", "$1"
					+ Matcher.quoteReplacement(exercisesString) + "$2");
			template = template.replaceAll("(\\W)TEMPLATEPATH(\\W)", "$1"
					+ Matcher.quoteReplacement(templatePath) + "$2");
			template = template.replaceAll("(\\W)DUEDATE(\\W)", "$1"
					+ Matcher.quoteReplacement(dueDateString) + "$2");

			// write temporary .tex file to temp directory
			FileOutputStream ofstream = new FileOutputStream(latexFile);
			BufferedWriter odstream = new BufferedWriter(
					new OutputStreamWriter(ofstream, "UTF8"));
			odstream.write(template);
			odstream.close();

			// call pdflatex to generate to the pdf file
			// TODO: check if linux conditional is necessary
			ProcessBuilder pb;
			if (Util.isLinux())
				pb = new ProcessBuilder(cmdList);
			else
				pb = new ProcessBuilder(cmd);

			Process p = pb.start();
			Scanner s = new Scanner(p.getInputStream()).useDelimiter("\n");
			while (s.hasNext()) {
				System.out.println(s.next());
			}

			// copy resultfile to "tempPDFfileforPreview.pdf" in temp directory
			File f = new File(path);
			File sourceFile = new File(latexFile.getAbsolutePath().replaceAll(
					".tex$", ".pdf"));
			FileUtils.copyFile(sourceFile, f);

			// copy file to svn working copy if flag is set
			if (copyFile)
				FileUtils.copyFile(f, new File(ExerciseSVN.SVNpath
						+ "exercisesheets/" + f.getName()));

			// remove temporary files
			File tmpFile = new File(latexFile.getAbsolutePath().replace(".tex", ".aux"));
			tmpFile.delete();
			tmpFile = new File(latexFile.getAbsolutePath().replace(".tex", ".log"));
			tmpFile.delete();
			tmpFile = new File(latexFile.getAbsolutePath().replace(".tex", ".out"));
			tmpFile.delete();
			tmpFile = new File(latexFile.getAbsolutePath().replace(".tex", ".pdf"));
			tmpFile.delete();
			latexFile.delete();
			
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

}
