package com.ejie.ad74a.rtf;

import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class RTFTemplateUtils {

	/**
	 * Genera en doc un nodo de tipo String válido para RTFTemplate
	 * 
	 * @param doc              Document
	 * @param etiqueta         String
	 * @param valor            String
	 * @param RTFTemplateItems Element
	 */
	public static void crearItemString(Document doc, String etiqueta, String valor, Element RTFTemplateItems) {

		Element RTFTemplateItem = doc.createElement("RTFTemplateItem");
		RTFTemplateItem.setAttribute("tipo", "String");
		RTFTemplateItem.setAttribute("etiqueta", etiqueta);
		RTFTemplateItems.appendChild(RTFTemplateItem);
		Element items = doc.createElement("items");
		RTFTemplateItem.appendChild(items);
		Element item = doc.createElement("item");
		item.setTextContent(valor);
		items.appendChild(item);
	}

	/**
	 * Genera en doc la estructura completa de nodos de tipo ListMap para
	 * RTFTemplate
	 * 
	 * @param doc              Document
	 * @param hmDatos          List<HashMap<String, String>>
	 * @param etiquetaPadre    String
	 * @param RTFTemplateItems Element
	 */
	public static void crearItemListMap(Document doc, List<HashMap<String, String>> hmDatos, String etiquetaPadre,
			Element RTFTemplateItems) {

		// Ahora hay que crear un elemento item por cada fila
		if (hmDatos != null && hmDatos.size() != 0) {
			Element RTFTemplateItem = doc.createElement("RTFTemplateItem");
			RTFTemplateItem.setAttribute("tipo", "ListMap");
			RTFTemplateItem.setAttribute("etiqueta", etiquetaPadre);
			RTFTemplateItems.appendChild(RTFTemplateItem);
			Element items = doc.createElement("items");
			RTFTemplateItem.appendChild(items);

			for (int i = 0; i < hmDatos.size(); i++) {
				Map<String, String> dato = null;
				dato = hmDatos.get(i);
				Element item = doc.createElement("item");
				items.appendChild(item);
				Element items2 = doc.createElement("items");
				item.appendChild(items2);
				// Ahora, un elemento item por cada hashmap
				Iterator iter = dato.entrySet().iterator();
				Map.Entry e;
				while (iter.hasNext()) {
					e = (Map.Entry) iter.next();
					Element itemHijo = doc.createElement("item");
					itemHijo.setAttribute("etiqueta", e.getKey().toString());
					itemHijo.setTextContent(e.getValue().toString());
					items2.appendChild(itemHijo);
				}
			}
		}
	}

	/**
	 * Genera en doc la estructura completa de nodos de tipo ListMap para
	 * RTFTemplate
	 * 
	 * @param doc              Document
	 * @param hmDatos          List<HashMap<String, String>>
	 * @param etiquetaPadre    String
	 * @param RTFTemplateItems Element
	 */
	public static void crearItemMap(Document doc, List<HashMap<String, String>> hmDatos, String etiquetaPadre,
			Element RTFTemplateItems) {

		Element RTFTemplateItem = doc.createElement("RTFTemplateItem");
		RTFTemplateItem.setAttribute("tipo", "Map");
		RTFTemplateItem.setAttribute("etiqueta", etiquetaPadre);
		RTFTemplateItems.appendChild(RTFTemplateItem);
		Element items = doc.createElement("items");
		RTFTemplateItem.appendChild(items);

		// Ahora hay que crear un elemento item por cada fila
		if (hmDatos != null) {
			for (int i = 0; i < hmDatos.size(); i++) {
				Map<String, String> dato = null;
				dato = hmDatos.get(i);

				// Ahora, un elemento item por cada hashmap
				Iterator iter = dato.entrySet().iterator();
				Map.Entry e;
				while (iter.hasNext()) {
					e = (Map.Entry) iter.next();
					Element itemHijo = doc.createElement("item");
					itemHijo.setAttribute("etiqueta", e.getKey().toString());
					itemHijo.setTextContent(e.getValue().toString());
					items.appendChild(itemHijo);
				}
			}
		}
	}

	/**
	 * Genera en doc la estructura completa de nodos de tipo List para RTFTemplate
	 * 
	 * @param doc              Document
	 * @param etiqueta         String
	 * @param hmDatos          List<String>
	 * @param RTFTemplateItems Element
	 */
	public static void crearItemList(Document doc, List<String> hmDatos, String etiqueta, Element RTFTemplateItems) {

		Element RTFTemplateItem = doc.createElement("RTFTemplateItem");
		RTFTemplateItem.setAttribute("tipo", "List");
		RTFTemplateItem.setAttribute("etiqueta", etiqueta);
		RTFTemplateItems.appendChild(RTFTemplateItem);
		Element items = doc.createElement("items");
		RTFTemplateItem.appendChild(items);

		// Ahora hay que crear un elemento item por cada fila
		if (hmDatos != null) {
			for (int i = 0; i < hmDatos.size(); i++) {
				String dato = "";
				dato = hmDatos.get(i);
				Element item = doc.createElement("item");
				item.setTextContent(dato);
				items.appendChild(item);
			}
		}
	}

	public static byte[] createXML(HashMap<String, String> datoS, HashMap<String, List<String>> datosListaS,
			HashMap<String, List<HashMap<String, String>>> datosMap,
			HashMap<String, List<HashMap<String, String>>> datosListaMap)
			throws ParserConfigurationException, Exception {

		DocumentBuilderFactory documentFactory = DocumentBuilderFactory.newInstance();

		DocumentBuilder documentBuilder = documentFactory.newDocumentBuilder();

		DOMImplementation domImpl = documentBuilder.getDOMImplementation();
		Document doc = domImpl.createDocument("", "RTFTemplate", null);

		// doc.setXmlVersion("1.0");
		// encoding="UTF-8"

		Element RTFTemplate = doc.getDocumentElement();

		RTFTemplate.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
		RTFTemplate.setAttribute("xsi:noNamespaceSchemaLocation", "..\\file\\schemaRTFTemplate.xsd");
		// doc.appendChild(RTFTemplate);

		Element RTFTemplateItems = doc.createElement("RTFTemplateItems");
		RTFTemplate.appendChild(RTFTemplateItems);

		// Los datos los tenemos en camposInformes

		// Datos de tipo String
		Iterator iter = datoS.entrySet().iterator();
		Map.Entry e;
		while (iter.hasNext()) {
			e = (Map.Entry) iter.next();
			RTFTemplateUtils.crearItemString(doc, e.getKey().toString(),
					e.getValue() != null ? e.getValue().toString() : "", RTFTemplateItems);

		}
		// Datos de tipo List
		if (datosListaS != null) {
			iter = datosListaS.entrySet().iterator();
			while (iter.hasNext()) {
				e = (Map.Entry) iter.next();
				List<String> lstGen = (ArrayList) e.getValue();
				RTFTemplateUtils.crearItemList(doc, lstGen, e.getKey().toString(), RTFTemplateItems);
			}
		}

		// Datos de tipo Map
		if (datosMap != null) {
			iter = datosMap.entrySet().iterator();
			while (iter.hasNext()) {
				e = (Map.Entry) iter.next();
				List<HashMap<String, String>> lstGenMap = (ArrayList) e.getValue();
				RTFTemplateUtils.crearItemMap(doc, lstGenMap, e.getKey().toString(), RTFTemplateItems);
			}
		}

		// Datos de tipo ListMap
		if (datosListaMap != null) {
			iter = datosListaMap.entrySet().iterator();
			while (iter.hasNext()) {
				e = (Map.Entry) iter.next();
				List<HashMap<String, String>> lstGenMap = (ArrayList) e.getValue();
				RTFTemplateUtils.crearItemListMap(doc, lstGenMap, e.getKey().toString(), RTFTemplateItems);
			}
		}
		TransformerFactory transformerFactory = TransformerFactory.newInstance();
		Transformer transformer = transformerFactory.newTransformer();

		DOMSource domSource = new DOMSource(doc); // pasos = "8";
		ByteArrayOutputStream bos = new ByteArrayOutputStream();
		StreamResult streamResult = new StreamResult(bos);
		transformer.transform(domSource, streamResult);

		/*
		 * DOMImplementationLS ls = (DOMImplementationLS) domImpl; LSSerializer lss =
		 * ls.createLSSerializer(); LSOutput lso = ls.createLSOutput();
		 * lso.setByteStream(System.out); lss.write(doc, lso);
		 */
		// } catch (ParserConfigurationException pce) {
		// pce.printStackTrace();
		// } catch (TransformerException tfe) {
		// tfe.printStackTrace();
		return bos.toByteArray();

	}

}
