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

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Vector;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

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 SAXHandler extends DefaultHandler {

	public static final int NONE = 0;
	public static final int TITLE = 1;
	public static final int AUTHOR = 2;
	public static final int TAGS = 4;
	public static final int CONTENT = 8;
	public static final int ATTACHEMENT = 16;

	private int state = NONE;
	private String content;

	private Vector<Memo> memos;
	private Vector<Category> categories;
	private HashMap<Long, Category> map;

	private Category category;
	private Memo memo;
	private File attachement;

	SAXHandler(Vector<Memo> memos) {
		this.memos = memos;
		this.memos.clear();
		this.categories = new Vector<Category>();
		this.map = new HashMap<Long, Category>();
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {

		if (qName.equals("category")) {
			this.category = new Category("");
			this.category.setiD(Long.parseLong(attributes.getValue("id")));
			this.category.setParentID(Long.parseLong(attributes
					.getValue("parent")));

			this.categories.add(this.category);
		}

		if (qName.equals("memo")) {
			this.memo = new Memo("", Boolean.parseBoolean(attributes
					.getValue("draft")));
			this.memo.setiD(Long.parseLong(attributes.getValue("id")));
			this.memo.setTimestamp(new Date(Long.parseLong(attributes
					.getValue("timestamp"))));
			this.memo.setCategoryID(Long.parseLong(attributes
					.getValue("category")));
			this.memo.setCategory(this.map.get(this.memo.getCategoryID()));
			this.memo.setAllCategories(this.categories);
			this.memos.add(this.memo);
		}

		if (qName.equals("title"))
			this.state = SAXHandler.TITLE;

		if (qName.equals("author"))
			this.state = SAXHandler.AUTHOR;

		if (qName.equals("tags"))
			this.state = SAXHandler.TAGS;

		if (qName.equals("content")) {
			this.state = SAXHandler.CONTENT;
			this.content = "";
		}

		if (qName.equals("attachements")) {
			this.memo.setFiles(new ArrayList<File>());
		}

		if (qName.equals("attachement")) {
			this.state = SAXHandler.ATTACHEMENT;
			this.attachement = new File();
			this.attachement.memo = this.memo;
			this.attachement.name = Base64Coder.decodeString(attributes
					.getValue("name"));
			this.memo.getFiles().add(this.attachement);
			this.content = "";
		}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {

		if (qName.equals("category")) {
			this.category = null;
		}

		if (qName.equals("memo")) {
			this.memo = null;
		}

		if (qName.equals("categories")) {
			Iterator<Category> iterator = this.categories.iterator();

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

				for (int i = 0; i < this.categories.size(); i++) {
					if (this.categories.elementAt(i).getiD().equals(
							current.getParentID()))
						current.setParentCategory(this.categories.elementAt(i));
					else if (this.categories.elementAt(i).getParentID().equals(
							current.getiD()))
						current.getChildCategories().add(
								this.categories.elementAt(i));
				}
				this.map.put(current.getiD(), current);
			}
		}

		if (qName.equals("content") && this.content.length() > 0) {
			this.memo.setContent(Base64Coder.decodeString(this.content));
			this.content = null;
		}

		if (qName.equals("attachement") && this.attachement != null) {
			this.attachement.content = Base64Coder
					.decode(content.toCharArray());
			this.attachement = null;
			this.content = null;
		}
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {

		String data = (new String(ch)).substring(start, start + length).trim();
		if (data.length() > 0) {
			if (this.category != null)
				this.category.setName(Base64Coder.decodeString(data));

			if (this.memo != null)
				switch (this.state) {
				case TITLE:
					this.memo.setTitle(Base64Coder.decodeString(data));
					break;
				case AUTHOR:
					this.memo.setAuthor(Base64Coder.decodeString(data));
					break;
				case CONTENT:
				case ATTACHEMENT:
					this.content = this.content.concat(data);
					break;
				case TAGS:
					String[] tags = Base64Coder.decodeString(data).split("\0");

					for (int x = 0; x < tags.length; x++) {
						Tag temp2 = new Tag(tags[x]);
						temp2.setMemo(this.memo);
						temp2.setMemoID(this.memo.getiD());
						this.memo.getTags().add(temp2);
					}
					break;
				}
		}
	}

	@Override
	public void endDocument() throws SAXException {
		super.endDocument();
	}
}
