package OOXMLconvert;

import java.io.FileOutputStream;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import org.jdom.DocType;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.Namespace;
import org.jdom.output.Format;
import org.jdom.output.XMLOutputter;

/**
 *
 * @author ferou
 */
public class XHTMLoutput {
	
	public XHTMLoutput() {
		// noop
	}

	/**
	 * Funkcia aplikuje dané namespace na všetkých potomkov
	 * @param el element, na ktorom sa má aplikovať namespace
	 * @param ns namespace
	 */
	private void useNamespaceForAllDesc(Element el, Namespace ns) {
		try {
			el.setNamespace(ns);
			List children = el.getChildren();
			Iterator iterator = children.iterator();
			while (iterator.hasNext()) {
				Element child = (Element) iterator.next();
				useNamespaceForAllDesc(child, ns);
			}
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + ": " + e.toString());
		}
	}
	
	/**
	 * Funkcia porovnáva dva elementy, či majú rovnaké formátovanie
	 * @param el1 prvý element na porovnanie
	 * @param el2 druhý element na porovnanie
	 * @return <i>true</i> ak majú elementy rovnaké formátovanie, <i>false</i> inak
	 */
	private static boolean isEqualStyle(Element el1, Element el2) {
		try {
			String classes1 = el1.getAttributeValue("class");
			String classes2 = el2.getAttributeValue("class");
			// kedze v celom programe pridavame CSS styly vo vopred urcenom poradi, staci porovnat
			boolean retBool = classes1.equals(classes2);
			return retBool;
		}
		catch (Exception e) {
			System.err.println("XHTMLoutput (isEqualStyle): " + e.toString());
			return false;
		}
	}
	
	/**
	 * Funkcia spojí dva span bloky ak majú rovnaké formátovanie
	 * @param el element na prehľadávanie rovnakých po sebe nasledujúcich blokov
	 */
	public static void mergeSpanBlocks(Element el) {
		try {
			LinkedList<Element> elementsToRemove = new LinkedList<Element>();
			List elChildren = el.getContent();
			Iterator elIterator = elChildren.iterator();
			Element lastSpan = null;
			while (elIterator.hasNext()) {
				Element elChild = null;
				try {
					elChild = (Element) elIterator.next();
				}
				catch (ClassCastException e) {
					// ak child nie je Element
					lastSpan = null;
					continue;
				}
				if (elChild.getName().equals("span")) {
					// ak bol posledny element tiez span...
					if (lastSpan != null) {
						if (isEqualStyle(elChild,lastSpan)) {
							// styly su rovnake, spoj elementy
							lastSpan.addContent(elChild.cloneContent());
							elementsToRemove.add(elChild);
						}
						else {
							lastSpan = elChild;
						}
					}
					else {
						lastSpan = elChild;
					}
				}
				else {
					lastSpan = null;
					mergeSpanBlocks(elChild);
				}
			}
			Iterator i = elementsToRemove.iterator();
			while (i.hasNext()) {
				Element elementToRemove = (Element)i.next();
				el.removeContent(elementToRemove);
			}
		}
		catch (Exception e) {
			System.err.println("XHTMLoutput (mergeSpanBlocks): " + e.toString());
		}
	}
	
	/**
	 * Funkcia, ktorá zapíše výstupné XHTML do súboru
	 * @param bodyEl body element XHTML dokumentu
	 * @return <i>true</i> ak nenastala chyba, <i>false</i> inak
	 */
	public boolean writeXHTML(Element bodyEl) {
		try {
			// najprv preformatuj bodyEl
			//mergeSpanBlocks(bodyEl);
			// sprav strukturu xhtml
			Namespace ns = Namespace.getNamespace("http://www.w3.org/1999/xhtml");
			Element htmlEl = new Element("html");
			Element headEl = new Element("head");
			Element titleEl = new Element("title");
			headEl.addContent(titleEl);
			Element metaEl = new Element("meta");
			metaEl.setAttribute("http-equiv", "Content-Type");
			metaEl.setAttribute("content", "text/html; charset=UTF-8");
			headEl.addContent(metaEl);
			if (Global.ooxmlParams.formatPreservingLevel > 0) {
				Element linkEl = new Element("link");
				linkEl.setAttribute("rel", "stylesheet");
				linkEl.setAttribute("type", "text/css");
				String relCssPath = Global.ooxmlParams.cssDir;
				linkEl.setAttribute("href", relCssPath);
				headEl.addContent(linkEl);
			}
			titleEl.setText("Office Open XML convert 1.0 - " + Global.ooxmlParams.docxSource.getName());
			htmlEl.addContent(headEl);
			htmlEl.addContent(bodyEl);
			Document xhtml = new Document(htmlEl);
			// pridaj doctype
			DocType dt = new DocType("html", "-//W3C//DTD XHTML 1.0 Strict//EN", "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd");
			xhtml.setDocType(dt);
			useNamespaceForAllDesc(htmlEl, ns);
			XMLOutputter xhtmlOut = new XMLOutputter();
			FileOutputStream out = new FileOutputStream(Global.ooxmlParams.xhtmlDest); 
			//xhtmlOut.setFormat(Format.getRawFormat());
			xhtmlOut.setFormat(Format.getHTMLFormat());
			xhtmlOut.output(xhtml, out);
			return true;
		}
		catch (Exception e) {
			System.err.println(this.getClass().getName() + ": " + e.toString());
			return false;
		}
	}
	

}
