package de.ugoe.cs.swe.memos.xml;

import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.Vector;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import de.ugoe.cs.swe.memos.database.DBUtility;
import de.ugoe.cs.swe.memos.database.DatabaseException;
import de.ugoe.cs.swe.memos.datamodel.Category;
import de.ugoe.cs.swe.memos.datamodel.File;
import de.ugoe.cs.swe.memos.datamodel.Memo;
import de.ugoe.cs.swe.memos.datamodel.Tag;
import de.ugoe.cs.swe.memos.misc.Base64Coder;

public class XMLInterface {
	private String filename;
	private Vector<Memo> memos;

	public XMLInterface(Vector<Memo> memos, String XMLfile) {
		this.filename = new String(XMLfile);
		this.memos = memos;
	}

	public void loadFromXML() {
		//this.memos = new Vector<Memo>();

		try {
			SAXParserFactory factory = SAXParserFactory.newInstance();
			SAXParser saxParser = factory.newSAXParser();

			saxParser.parse(this.filename, new SAXHandler(this.memos));
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public void saveToXML() {
		if ((new java.io.File(this.filename)).delete())
			System.out.println("\"" + this.filename
					+ "\" already existed, so I dropped it.");

		try {
			FileWriter fstream = new FileWriter(this.filename);
			BufferedWriter out = new BufferedWriter(fstream);

			System.out.println("Writing XML headers...");
			writeXMLHeader(out);

			out
					.write("<export timestamp=\"" + (new Date()).getTime()
							+ "\">\n");

			System.out.println("Exporting categories...");
			writeCategories(out);

			System.out.println("Exporting memos...");
			writeMemos(out);

			out.write("</export>\n");
			out.close();

			System.out.println("Done!!");
		} catch (Exception e) {
			System.err.println("Error: " + e.getMessage());
		}
	}

	private String fetchTagsFromMemo(Memo memo) {
		ArrayList<Tag> tags = new ArrayList<Tag>();
		String tbr = "";

		try {
			tags = DBUtility.getInstance().getTagsByMemo(memo);
		} catch (DatabaseException e) {
			System.out.println("Could not fetch tag for memo. Sorry.");
		}

		Iterator<Tag> iterator = tags.iterator();

		while (iterator.hasNext())
			tbr += iterator.next().getName() + "\0";

		return tbr;
	}

	private void writeXMLHeader(BufferedWriter out) {
		try {
			out.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone="
					+ "\"no\"?>\n");
		} catch (IOException e) {
			System.out.println("Could not write XML headers, sorry.");
		}
	}

	private void writeCategories(BufferedWriter out) {
		Vector<Category> categories = new Vector<Category>();

		try {
			categories = DBUtility.getInstance().queryCategories();
		} catch (DatabaseException e) {
			System.out.println("Could not fetch categories, sorry.");
		}

		try {
			out.write("\t<categories>\n");

			Iterator<Category> iterator = categories.iterator();

			while (iterator.hasNext()) {
				Category current = iterator.next();

				out.write("\t\t<category id=\"" + current.getiD()
						+ "\" parent=\"" + current.getParentID() + "\">\n");
				out.write("\t\t\t<name>"
						+ Base64Coder.encodeString(current.getName())
						+ "</name>\n");
				out.write("\t\t</category>\n");
			}

			out.write("\t</categories>\n");

		} catch (IOException e) {
			System.out.println("Could not export categories, sorry.");
		}
	}

	private void writeMemos(BufferedWriter out) throws IOException {
		try {
			out.write("\t<memos>\n");

			Iterator<Memo> iterator = this.memos.iterator();
			String content = new String();

			while (iterator.hasNext()) {
				Memo current = iterator.next();

				try {
					content = DBUtility.getInstance().getMemoByID(
							current.getiD()).getContent();
				} catch (Exception e) {
					System.out.println("Could not fetch memo by id. Sorry.");
				}
				if (content == null)
					content = "";
				// content = splitLines(Base64Coder.encodeString(content));
				content = Base64Coder.encodeString(content);

				out.write("\t\t<memo id=\"" + current.getiD()
						+ "\" timestamp=\"" + current.getTimestamp().getTime()
						+ "\" draft=\"" + current.isDraft() + "\" category=\""
						+ current.getCategoryID() + "\">\n");

				out.write("\t\t\t<title>"
						+ Base64Coder.encodeString(current.getTitle())
						+ "</title>\n");
				out.write("\t\t\t<author>"
						+ Base64Coder.encodeString(current.getAuthor())
						+ "</author>\n");
				out.write("\t\t\t<tags>"
						+ Base64Coder.encodeString(fetchTagsFromMemo(current))
						+ "</tags>\n");

				out.write("\t\t\t<content>" + content + "</content>\n");
				out.write("\t\t\t<attachements>\n");

				ArrayList<File> files = new ArrayList<File>();

				try {
					files = DBUtility.getInstance().getFilesByMemo(current);
				} catch (DatabaseException e) {
					System.out
							.println("Could not fetch files from database. Sorry;");
				}

				Iterator<File> fileIterator = files.iterator();

				while (fileIterator.hasNext()) {
					File currentFile = fileIterator.next();

					out.write("\t\t\t\t<attachement name=\""
							+ Base64Coder.encodeString(currentFile.name)
							+ "\">\n");

					ByteArrayOutputStream temp = new ByteArrayOutputStream();
					DBUtility.getInstance().getFileContent(currentFile, temp);

					String fileContent = new String(Base64Coder.encode(temp
							.toByteArray()));

					out.write("\t\t\t\t\t" + fileContent + "\n");
					out.write("\t\t\t\t</attachement>\n");
				}

				out.write("\t\t\t</attachements>\n");
				out.write("\t\t</memo>\n");
			}

			out.write("\t</memos>\n");

		} catch (IOException e) {
			System.out.println("Could not export memos, sorry.");
			throw e;
		}

	}

	public static void main(String[] args) {
		Vector<Memo> allMemos = new Vector<Memo>();

		// try {
		// allMemos = DBUtility.getInstance().queryMemos();
		// } catch (DatabaseException e) {
		// System.out.println("Could not fetch memos. Sorry.");
		// }

		String export = System.getProperty("user.home")
				+ System.getProperty("file.separator") + "export.xml";

		XMLInterface worker = new XMLInterface(allMemos, export);
		// worker.saveToXML();

		worker.loadFromXML();
	}
}