/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and Others
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Daisuke SATO - initial API and implementation
 *******************************************************************************/
package org.eclipse.actf.ai.audio.description.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.Stack;

import org.eclipse.actf.ai.audio.description.IMetadata;
import org.eclipse.actf.ai.audio.description.IMetadataProvider;
import org.eclipse.actf.ai.xmlstore.IXMLInfo;
import org.eclipse.actf.ai.xmlstore.XMLStoreException;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

public class MetadataProviderImpl implements IMetadataProvider {

	private static class Key {
		public String id;

		public String lang;

		public Key(String id, String lang) {
			this.id = id;
			if (lang == null || lang.length() == 0) {
				this.lang = "";
			} else {
				this.lang = (new Locale(lang)).getLanguage();
			}
		}

		@Override
		public int hashCode() {
			return toString().hashCode();
		}

		@Override
		public boolean equals(Object o) {
			return toString().equals(o.toString());
		}

		@Override
		public String toString() {
			return id + lang;
		}
	}

	private HashMap<Key, ArrayList<IMetadata>> metadataList = new HashMap<Key, ArrayList<IMetadata>>();

	private ArrayList<IMetadata> metadata;

	private ArrayList<IXMLInfo> entries;

	private Locale locale = null;

	public MetadataProviderImpl(ArrayList<IXMLInfo> entries) {
		this.entries = entries;
	}

	public void reload() {
		metadataList.clear();
		readFile();
	}

	private Stack<String> langStack = new Stack<String>();

	private class BaseHandler extends DefaultHandler {
		private BaseHandler back;

		private IXMLInfo entry;

		public BaseHandler(BaseHandler back, IXMLInfo entry) {
			this.back = back;
			this.entry = entry;
		}

		public BaseHandler(BaseHandler back) {
			this.back = back;
			this.entry = back.getEntry();
		}

		@Override
		public void startElement(String uri, String localName, String qName,
				Attributes attributes) throws SAXException {
			if (attributes.getValue("xml:lang") != null) {
				langStack.push(attributes.getValue("xml:lang"));
			} else {
				langStack.push(langStack.peek() + "");
			}
		}

		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			langStack.pop();
			getEntry().setContentHandler(back);
		}

		public IXMLInfo getEntry() {
			return entry;
		}
	}

	private class AllHandler extends BaseHandler {
		private boolean altFlag;

		public AllHandler(IXMLInfo entry) {
			super(null, entry);
			langStack.clear();
			langStack.push("");
		}

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

			if (altFlag) {
				if ("item".equals(localName)) {
					String importance = attributes.getValue("importance");
					if (importance == null || importance.length() == 0) {
						importance = "middle";
					}
					getEntry().setContentHandler(
							new ItemHandler(this, importance));
				}
			} else {
				if ("alternative".equals(localName)) {
					String type = attributes.getValue("type");
					if (type != null && type.equals("audio-description")) {
						altFlag = true;
					}
				}
				if ("volumeLevel".equals(localName)) {
					// do nothing
				}
			}
		}

		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			if ("alternative".equals(localName)) {
				altFlag = false;
			}
			// super.endElement(uri, localName, qName);
		}
	}

	private class ItemHandler extends BaseHandler {
		private boolean descFlag = false;

		private boolean startFlag = false;

		private boolean durationFlag = false;

		private boolean additionFlag = false;

		private boolean waveFlag = false;

		private StringBuffer buf = new StringBuffer();

		private String start;

		private String duration;

		private ArrayList<String> speed = new ArrayList<String>();

		private ArrayList<String> gender = new ArrayList<String>();

		private ArrayList<String> desc = new ArrayList<String>();

		private ArrayList<String> lang = new ArrayList<String>();

		private ArrayList<String> extended = new ArrayList<String>();

		/*
		 * experimental private ArrayList<String> additions = new
		 * ArrayList<String>();
		 * 
		 * private ArrayList<String> additionsLang = new ArrayList<String>();
		 * 
		 * private ArrayList<String> additionsSpeed = new ArrayList<String>();
		 * 
		 * private ArrayList<String> additionsGender = new ArrayList<String>();
		 */

		private ArrayList<String> waveLocal = new ArrayList<String>();

		private String importance;

		public ItemHandler(BaseHandler back, String importance) {
			super(back);
			this.importance = importance;
		}

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

			if ("start".equals(localName)) {
				if (attributes.getValue("type").equals("relTime")) {
					startFlag = true;
				}
			} else if ("duration".equals(localName)) {
				durationFlag = true;
			} else if ("description".equals(localName)) {
				descFlag = true;
				speed.add(attributes.getValue("speed"));
				gender.add(attributes.getValue("gender"));
				extended.add(attributes.getValue("extended"));
				/*
				 * } else if ("addition".equals(localName)) { additionFlag =
				 * true; additionsSpeed.add(attributes.getValue("speed"));
				 * additionsGender.add(attributes.getValue("gender"));
				 */
			} else if ("wave".equals(localName)) {
				waveFlag = true;
				waveLocal.add(attributes.getValue("local"));
			}

		}

		@Override
		public void characters(char[] ch, int start, int length)
				throws SAXException {
			if (startFlag) {
				buf.append(ch, start, length);
			} else if (durationFlag) {
				buf.append(ch, start, length);
			} else if (descFlag) {
				buf.append(ch, start, length);
			} else if (additionFlag) {
				buf.append(ch, start, length);
			} else if (waveFlag) {
				buf.append(ch, start, length);
			}
		}

		@Override
		public void endElement(String uri, String localName, String qName)
				throws SAXException {
			if ("start".equals(localName)) {
				startFlag = false;
				start = buf.toString();
				buf.delete(0, buf.length());
			} else if ("duration".equals(localName)) {
				durationFlag = false;
				duration = buf.toString();
				buf.delete(0, buf.length());
			} else if ("description".equals(localName)) {
				descFlag = false;
				desc.add(buf.toString());
				lang.add(langStack.peek());
				buf.delete(0, buf.length());
				/*
				 * } else if ("addition".equals(localName)) { additionFlag =
				 * false; additions.add(buf.toString());
				 * additionsLang.add(langStack.peek()); buf.delete(0,
				 * buf.length());
				 */
			} else if ("wave".equals(localName)) {
				waveFlag = false;
				// waveLang.add(langStack.peek()); //TODO
				buf.delete(0, buf.length());
			} else if ("item".equals(localName)) {

				for (int i = 0; i < desc.size(); i++) {
					MetadataImpl mi = new MetadataImpl(start, duration, desc
							.get(i), lang.get(i), importance, speed.get(i),
							gender.get(i), extended.get(i));

					/*
					 * for (int j = 0; j < additions.size(); j++) { if
					 * (additionsLang.get(j).equals(lang.get(i))) {
					 * mi.setAddition(additions.get(j));
					 * mi.setAdditionGender(additionsGender.get(j));
					 * mi.setAdditionSpeed(additionsSpeed.get(j)); } }
					 */

					for (int j = 0; j < waveLocal.size(); j++) {
						// TODO lang
						mi.setWavLocal(waveLocal.get(j));
					}

					// System.out.println(start + ", " + duration + ", " +
					// desc.get(i) + ", " + lang.get(i));

					Key key = new Key(getEntry().getDocumentation(), lang
							.get(i));

					ArrayList<IMetadata> list = metadataList.get(key);

					if (list == null) {
						list = new ArrayList<IMetadata>();
						metadataList.put(key, list);
					}
					list.add(mi);
				}
				super.endElement(uri, localName, qName);
			}
		}
	}

	private void readFile() {
		for (int i = 0; i < entries.size(); i++) {
			IXMLInfo entry = entries.get(i);

			AllHandler ah = new AllHandler(entry);
			entry.setContentHandler(ah);
			try {
				entry.startSAX();
			} catch (XMLStoreException e) {
				e.printStackTrace();
			} catch (SAXException e) {
				e.printStackTrace();
			}
		}
	}

	public void setLocale(Locale locale) {
		this.locale = locale;
	}

	ArrayList<ArrayList<IMetadata>> alternatives;

	public void prepareMetadata() {
		prepareMetadata(this.locale);
	}

	public void prepareMetadata(Locale locale) {
		Set<Key> keys = metadataList.keySet();
		alternatives = new ArrayList<ArrayList<IMetadata>>();
		for (Iterator<Key> i = keys.iterator(); i.hasNext();) {
			Key key = i.next();
			if (key.lang.equals(locale.getLanguage())) {
				alternatives.add(metadataList.get(key));
			}
		}
		if (alternatives.size() > 0)
			setMetadata(alternatives.get(0));
	}

	public void setMetadata(ArrayList<IMetadata> metadata) {
		this.metadata = metadata;
	}

	public IMetadata getItem(int index) {
		if (0 <= index && index < metadata.size())
			return metadata.get(index);
		return null;
	}

	public ArrayList<IMetadata> getAllItems() {
		return metadata;
	}

	public int getIndex(int position) {
		if (metadata == null)
			return 0;

		int ret = 0;
		for (int i = 0; i < metadata.size(); i++) {
			if (metadata.get(i).getStartTime() >= position) {
				ret = i - 1;
				return ret;
			}
		}
		return metadata.size() - 1;
	}

	public int getSize() {
		if (metadata == null)
			return 0;
		return metadata.size();
	}

	public boolean hasMetadata() {
		if (metadata == null)
			return false;
		return metadata.size() > 0;
	}
}
