package com.bernard.mcq.formQuiz;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.filechooser.FileNameExtensionFilter;

import org.jdom.Element;
import org.jopendocument.dom.spreadsheet.Cell;
import org.jopendocument.dom.spreadsheet.Sheet;
import org.jopendocument.dom.spreadsheet.SpreadSheet;

public class MainParser {

	static JFileChooser inputChooser;
	static JFileChooser outputChooser;

	public static final byte[] appBernardKey = { 0b00100010, 0b01001001 };
	public static final byte[] bernardSignature = { 0b00011001, 0b01101101 };
	public static final Charset UTF_8 = Charset.forName("UTF-8");

	public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException, FileNotFoundException {
		
		System.setOut(new PrintStream(new FileOutputStream("out.log")));
		
		inputChooser = new JFileChooser();
		inputChooser.addChoosableFileFilter(new FileNameExtensionFilter("Libre office calc sheet", "ods"));
		while (true) {
			int returnVal = inputChooser.showOpenDialog(null);
			if (returnVal == JFileChooser.APPROVE_OPTION) {
				File inputFile = inputChooser.getSelectedFile();
				outputChooser = new JFileChooser();
				outputChooser.addChoosableFileFilter(new FileNameExtensionFilter("Bernard file", "bernard"));
				int returnVal2 = outputChooser.showSaveDialog(null);
				if (returnVal2 == JFileChooser.APPROVE_OPTION) {
					String outputName = outputChooser.getSelectedFile().getName();
					outputName += !outputName.endsWith(".bernard") ? ".bernard" : "";
					File saveDirectory = outputChooser.getCurrentDirectory();
					String outQuizID;
					do {
						outQuizID = JOptionPane.showInputDialog(null, "What is the quiz's quizID ?", "QuizID ?",
								JOptionPane.QUESTION_MESSAGE);
					} while (!outQuizID.matches("[0-9]+"));
					int quizID = Integer.parseInt(outQuizID);
					String name = JOptionPane.showInputDialog(null, "What is the quiz's name ?", "Name ?",
								JOptionPane.QUESTION_MESSAGE);
					String author = JOptionPane.showInputDialog(null, "Who is the quiz's author ?", "Author ?",
								JOptionPane.QUESTION_MESSAGE);
					Sheet sheet;
					try {
						sheet = SpreadSheet.createFromFile(inputFile).getSheet(0);

						int row = 0;
						List<String> formsMarkers = new ArrayList<>();
						while (true) {
							Cell<SpreadSheet> cell = sheet.getCellAt(0, row);
							System.out.println("\"" + cell.getTextValue() + "\"");
							String tv = getCellContent(cell);
							if (tv == null || tv.isEmpty())
								break;
							formsMarkers.add(cell.getTextValue());
							row++;
						}
						String endTag = formsMarkers.get(formsMarkers.size() - 1);
						formsMarkers.remove(formsMarkers.size() - 1);

						List<Map<Integer,List<String>>> verben = new ArrayList<>();

						int col = 1;
						int formID;
						int tempFormID;
						while (!sheet.getCellAt(col, 0).getTextValue().isEmpty()) {
							//New Item
							row = 0;
							formID = -1;
							Map<Integer,List<String>> forms = new HashMap<>();
							
							String cellValue;
							while (!(cellValue = getCellContent(sheet.getCellAt(col,row))).equals(endTag)) {
								
								if ((tempFormID = formsMarkers.indexOf(cellValue))!=-1){
									formID = tempFormID;
									forms.put(formID, new ArrayList<String>());
								}else if (cellValue != null && !cellValue.isEmpty() && forms.get(formID) != null)
									forms.get(formID).add(cellValue);
								row++;
								System.out.println("Future test : ("+col+";"+row+")");
							}
							verben.add(forms);
							col++;
						}

						System.out.println("Final : ");
						System.out.println(verben.toString());

						// Save as quiz file
						File saveFile = new File(saveDirectory, outputName);
						if (saveFile.exists()) {
							int returnVal3 = JOptionPane.showConfirmDialog(null,
									"Do you really want to overwrite " + saveFile.getPath(), "Overwrite ?",
									JOptionPane.YES_NO_OPTION);
							if (returnVal3 != JOptionPane.YES_OPTION)
								continue;
							saveFile.delete();
						}
						if (saveFile.canWrite())
							error(saveFile.getAbsolutePath() + " is unwritable !!!");
						if (saveFile.isDirectory())
							error(saveFile.getAbsolutePath() + " is a directory !!!");
						if (!saveFile.exists()) {
							saveFile.createNewFile();
						}
						DataOutputStream dos = new DataOutputStream(new FileOutputStream(saveFile));
						
						// Writing Bernard signature
						dos.write(bernardSignature);

						// Writing Bernard key
						dos.write(appBernardKey);
						
						//QuizMetadata
						
						dos.writeInt(name.getBytes().length);
						dos.write(name.getBytes());
						dos.writeInt(author.getBytes().length);
						dos.write(author.getBytes());
						dos.writeLong(0);
						dos.writeInt(quizID);
						dos.writeBoolean(false);

						//QuizPayload
						
						// Writing quizType key
						dos.writeInt(quizID);

						// Writing quiz
						dos.writeInt(verben.size());
						for (Map<Integer,List<String>> forms : verben) {
							dos.writeInt(forms.size());
							for (Map.Entry<Integer,List<String>> entry : forms.entrySet()) {
								if (entry.getValue().size() <= 0) {
									dos.writeInt(-1);//FormID
									dos.writeInt(0);
									System.err.println("This clause should not be executed");
								} else {
									dos.writeInt(entry.getKey());
									dos.writeInt(entry.getValue().get(0).getBytes(UTF_8).length);
									dos.write(entry.getValue().get(0).getBytes(UTF_8));
									dos.writeInt(entry.getValue().size() - 1);
									for (int i = 1; i < entry.getValue().size(); i++) {
										dos.writeInt(entry.getValue().get(i).getBytes(UTF_8).length);
										dos.write(entry.getValue().get(i).getBytes(UTF_8));
									}
								}

							}
						}

						dos.close();

						int resultVal4 = JOptionPane.showConfirmDialog(null,
								"Fichier �crit !!! Voulez vous parser un autre document ?", "Done",
								JOptionPane.YES_NO_OPTION);

						if (resultVal4 != JOptionPane.YES_OPTION)
							break;

					} catch (IOException e) {
						error("Impossible de lire le fichier , " + e.getClass().getName());
					}

				} else {
					System.out.println("Bye !");
					return;
				}

			} else {
				System.out.println("Bye !");
				return;
			}
		}

	}
	public static String getCellContent(Cell<SpreadSheet> cell){
		try{
			//String toString = new String(((Element)cell.getElement().getContent(0)).getContent(0).getValue().getBytes(UTF_8),UTF_8);
			//System.out.println(toString + Arrays.toString(toString.getBytes(UTF_8)));
			return cell.getTextValue();//toString;
		}catch(Exception e){
			System.err.println("(Un)expected Exception : " + e.getClass().getName());
		}
		return null;
	}

	public static void error(String text) {
		System.out.println(text);
		JOptionPane.showMessageDialog(null, text, "Error !!!!!", JOptionPane.ERROR_MESSAGE);
		System.exit(1);
	}

}
