package com.ejie.aa20b.informes.listados;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

import javax.servlet.http.HttpServletRequest;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import com.ejie.aa20b.classes.Aa20bFecha;
import com.ejie.aa20b.model.PrevAnual;
import com.ejie.aa20b.model.TablaPlanificacion;
import com.ejie.aa20b.util.Aa20bConstantes;

public class PlanAnualEdif {
	private static final Logger logger = LoggerFactory
			.getLogger(PlanAnualEdif.class);

	/* Imprimir */
	@SuppressWarnings({ "rawtypes", "unchecked", "null" })
	public Document getFoPlanAnualEdifXml(HttpServletRequest request,
			Locale locale, ArrayList listaPartes, PrevAnual filtro) {
		PlanAnualEdif.logger.info("getFoPlanAnualEdifXml");

		String idioma = locale.getLanguage();
		Integer[] arrayTiempos = null;
		Document doc = null;
		Element rootElement = null;
		try {
			DocumentBuilderFactory docFactory = DocumentBuilderFactory
					.newInstance();

			DocumentBuilder docBuilder = docFactory.newDocumentBuilder();

			// root elements

			doc = docBuilder.newDocument();
			rootElement = doc.createElement("report");
			doc.appendChild(rootElement);

			/* INSERTAMOS EL AÑO A LA RAIZ */
			Element anioEl = doc.createElement("Anio");
			rootElement.appendChild(anioEl);
			anioEl.appendChild(doc.createTextNode(filtro.getAnio() != null ? filtro
					.getAnio().toString() : " - "));
			/* FIN INSERTAR AÑO */

			/* INSERTAMOS EL FILTRO TERRITORIO */
			Element fTerri = doc.createElement("filtroTerritorio");
			rootElement.appendChild(fTerri);
			if (filtro.getTerritorio() != null) {
				fTerri.appendChild(doc.createTextNode(filtro.getTerritorio()
						.equals("") ? " " : filtro.getTerritorio()));
			} else {
				fTerri.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO TERRITORIO */

			/* INSERTAMOS EL FILTRO ZONA */
			Element fZona = doc.createElement("filtroZona");
			rootElement.appendChild(fZona);
			if (filtro.getZona() != null) {
				fZona.appendChild(doc.createTextNode(filtro.getZona()
						.equals("") ? " " : filtro.getZona()));
			} else {
				fZona.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO ZONA */

			/* INSERTAMOS EL FILTRO PLANTA */
			Element fPlanta = doc.createElement("filtroPlanta");
			rootElement.appendChild(fPlanta);
			if (filtro.getPlanta() != null) {
				fPlanta.appendChild(doc.createTextNode(filtro.getPlanta()
						.equals("") ? " " : filtro.getPlanta()));
			} else {
				fPlanta.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO PLANTA */

			/* INSERTAMOS EL FILTRO SITUACION */
			Element fSituacion = doc.createElement("filtroSituacion");
			rootElement.appendChild(fSituacion);
			if (filtro.getSituacion() != null) {
				fSituacion.appendChild(doc.createTextNode(filtro.getSituacion()
						.equals("") ? " " : filtro.getSituacion()));
			} else {
				fSituacion.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO SITUACION */

			/* INSERTAMOS EL FILTRO MANTENIMIENTO */
			Element fMant = doc.createElement("filtroMant");
			rootElement.appendChild(fMant);
			if (filtro.getTipoMantenimiento() != null) {
				fMant.appendChild(doc.createTextNode(filtro
						.getTipoMantenimiento().equals("") ? " " : filtro
						.getTipoMantenimiento()));
			} else {
				fMant.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO MANTENIMIENTO */

			/* INSERTAMOS EL FILTRO GAMA */
			Element fGama = doc.createElement("filtroGama");
			rootElement.appendChild(fGama);
			if (filtro.getGama() != null) {
				fGama.appendChild(doc.createTextNode(filtro.getGama()
						.equals("") ? " " : filtro.getGama()));
			} else {
				fGama.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO GAMA */

			/* INSERTAMOS EL FILTRO CONTRATA */
			Element fContrata = doc.createElement("filtroContrata");
			rootElement.appendChild(fContrata);
			if (filtro.getParaContrata() != null) {
				fContrata.appendChild(doc.createTextNode(filtro
						.getParaContrata().equals("") ? " " : filtro
						.getParaContrata()));
			} else {
				fContrata.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO CONTRATA */

			/* INSERTAMOS EL FILTRO MAQUINA */
			Element fMaquina = doc.createElement("filtroMaquina");
			rootElement.appendChild(fMaquina);
			if (filtro.getMaquina() != null) {
				fMaquina.appendChild(doc.createTextNode(filtro.getMaquina()
						.equals("") ? " " : filtro.getMaquina()));
			} else {
				fMaquina.appendChild(doc.createTextNode(" "));
			}
			/* FIN INSERTAMOS EL FILTRO MAQUINA */

			/* INSERTAMOS EL FILTRO INCLUIR BAJAS */
			Element fIncBaja = doc.createElement("filtroInclBaja");
			rootElement.appendChild(fIncBaja);
			if (filtro.getIncluirBaja() != null && filtro.getIncluirBaja() == 1) {
				if (idioma.equals(Aa20bConstantes.IDIOMA_EUSKERA)) {
					fIncBaja.appendChild(doc.createTextNode("BAI"));
				} else {
					fIncBaja.appendChild(doc.createTextNode("SI"));
				}
			} else {
				if (idioma.equals(Aa20bConstantes.IDIOMA_EUSKERA)) {
					fIncBaja.appendChild(doc.createTextNode("EZ"));
				} else {
					fIncBaja.appendChild(doc.createTextNode("NO"));
				}
			}
			/* FIN INSERTAMOS EL FILTRO INCLUIR BAJAS */

			/* INSERTAMOS LA FECHA DE HOY A LA RAIZ */
			Element fechaHoyEl = doc.createElement("fechaHoy");

			java.util.Date fechaHoy = new Date();

			String fechaString = Aa20bFecha.getFecha(fechaHoy);
			Integer diaSemana = fechaHoy.getDay() + 1;
			String fechaHoyString = "";
			if (idioma.equals(Aa20bConstantes.IDIOMA_EUSKERA)) {
				fechaHoyString = Aa20bFecha.convertirFechaCompletaEu(
						fechaString, diaSemana);

			} else {
				fechaHoyString = Aa20bFecha.convertirFechaCompleta(fechaString,
						diaSemana);
			}

			rootElement.appendChild(fechaHoyEl);
			fechaHoyEl.appendChild(doc
					.createTextNode(fechaHoyString == null ? " "
							: fechaHoyString));
			/* FIN INSERTAR FECHA DE HOY */

			// Element listadoEl = doc.createElement("listado");
			// Rellenamos una registro a vacios en caso de que no haya
			// resultados para poder montar el xml y así no nos dé error el pdf
			if (listaPartes.size() == 0) {
				TablaPlanificacion tablaVacia = new TablaPlanificacion();
				tablaVacia.setIdmaquina((long) 0);
				listaPartes.add(tablaVacia);
			}

			// Añadimos los meses del año
			String[] letrasMeses;
			try {
				letrasMeses = Aa20bFecha.letraMesSemana(filtro.getAnio());
			} catch (Exception e) {
				letrasMeses = null;
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			for (int a = 0; a < 54; a++) {
				Element mesesEl = doc.createElement("MES");
				rootElement.appendChild(mesesEl);
				mesesEl.appendChild(doc.createTextNode(letrasMeses[a] + ""));
			}

			// Añadimos las SEMANAS del año
			for (int a = 0; a < 54; a++) {
				Element semEl = doc.createElement("SEM");
				rootElement.appendChild(semEl);
				semEl.appendChild(doc.createTextNode(a + ""));
			}

			/*
			 * NUMFILAS - INSERTAMOS contador de filas para que no se pinte la
			 * tabla si no hay datos
			 */
			Element numFilasEl = doc.createElement("numFilas");
			rootElement.appendChild(numFilasEl);
			numFilasEl.appendChild(doc.createTextNode(Integer
					.toString(listaPartes.size())));
			/* FIN NUMFILAS */

			Element listadoEl = doc.createElement("listado");
			Element operacionEl = null;
			Element gamaEl = null;
			Element edificioEl = null;
			Element zonaEl = null;
			Element plantaEl = null;
			Boolean esPrimero = true;
			String gama = "";
			String edificio = "";
			String zona = "";
			String planta = "";
			Integer[] arrayTotalGama = null;
			arrayTotalGama = new Integer[54];
			Integer[] arrayTotalEdificio = null;
			arrayTotalEdificio = new Integer[54];
			Integer[] arrayTotalZona = null;
			arrayTotalZona = new Integer[54];
			Integer[] arrayTotalPlanta = null;
			arrayTotalPlanta = new Integer[54];

			for (int i = 0; i < listaPartes.size(); i++) {
				TablaPlanificacion laFila = new TablaPlanificacion();
				laFila = (TablaPlanificacion) listaPartes.get(i);
				if (esPrimero) {
					gamaEl = doc.createElement("GAMA");
					gamaEl.setAttribute("dGama", laFila.getGama() == null ? ""
							: laFila.getGama().toString());
					edificioEl = doc.createElement("EDIFICIO");
					edificioEl.setAttribute("dEdificio",
							laFila.getEdificio() == null ? "" : laFila
									.getEdificio().toString());
					zonaEl = doc.createElement("ZONA");
					zonaEl.setAttribute("dZona", laFila.getZona() == null ? ""
							: laFila.getZona().toString());
					plantaEl = doc.createElement("PLANTA");
					plantaEl.setAttribute("dPlanta",
							laFila.getPlanta() == null ? "" : laFila
									.getPlanta().toString());
				}

				// Si es una nueva Planta pero dentro de la misma Zona, Edificio
				// y Gama
				if (!planta.equals(laFila.getPlanta().toString())
						&& zona.equals(laFila.getZona().toString())
						&& edificio.equals(laFila.getEdificio().toString())
						&& gama.equals(laFila.getGama().toString())
						&& !esPrimero) {
					// Cerramos los tag incluidos los hijos
					zonaEl.appendChild(plantaEl);
					// Totales por Planta para la anterior Planta.
					crearTotalesPlanta(arrayTotalPlanta, doc, plantaEl);

					plantaEl = doc.createElement("PLANTA");
					plantaEl.setAttribute("dPlanta", laFila.getPlanta()
							.toString());
					// Inicializar valores
					arrayTotalPlanta = new Integer[54];
				}

				// Si es una nueva Zona pero dentro del mismo Edificio y gama
				if (!zona.equals(laFila.getZona().toString())
						&& edificio.equals(laFila.getEdificio().toString())
						&& gama.equals(laFila.getGama().toString())
						&& !esPrimero) {
					// Cerramos los tag incluidos los hijos
					zonaEl.appendChild(plantaEl);
					edificioEl.appendChild(zonaEl);

					// Totales por Planta para la anterior Planta.
					crearTotalesPlanta(arrayTotalPlanta, doc, plantaEl);
					plantaEl = doc.createElement("PLANTA");
					plantaEl.setAttribute("dPlanta", laFila.getPlanta()
							.toString());
					// Inicializar valores
					arrayTotalPlanta = new Integer[54];

					// Totales por Zona para la anterior Zona.
					crearTotalesZona(arrayTotalZona, doc, zonaEl);
					zonaEl = doc.createElement("ZONA");
					zonaEl.setAttribute("dZona", laFila.getZona().toString());
					// Inicializar valores
					arrayTotalZona = new Integer[54];

				}

				// Si es un nuevo edificio pero dentro de la misma Gama
				if (!edificio.equals(laFila.getEdificio().toString())
						&& gama.equals(laFila.getGama().toString())
						&& !esPrimero) {
					// Cerramos los tag incluidos los hijos
					zonaEl.appendChild(plantaEl);
					edificioEl.appendChild(zonaEl);
					gamaEl.appendChild(edificioEl);

					// Totales por Planta para la anterior Planta.
					crearTotalesPlanta(arrayTotalPlanta, doc, plantaEl);

					plantaEl = doc.createElement("PLANTA");
					plantaEl.setAttribute("dPlanta", laFila.getPlanta()
							.toString());
					// Inicializar valores
					arrayTotalPlanta = new Integer[54];

					// Totales por Zona para la anterior Zona.
					crearTotalesZona(arrayTotalZona, doc, zonaEl);
					zonaEl = doc.createElement("ZONA");
					zonaEl.setAttribute("dZona", laFila.getZona().toString());
					// Inicializar valores
					arrayTotalZona = new Integer[54];

					// Totales por Edificio para la anterior Edificio.
					crearTotalesEdificio(arrayTotalEdificio, doc, edificioEl);
					edificioEl = doc.createElement("EDIFICIO");
					edificioEl.setAttribute("dEdificio", laFila.getEdificio()
							.toString());
					// Inicializar valores
					arrayTotalEdificio = new Integer[54];
				}

				// Si es una nueva Gama
				if (!gama.equals(laFila.getGama().toString()) && !esPrimero) {
					// es una nueva Gama. Cerramos todos los tag en cadena
					zonaEl.appendChild(plantaEl);
					edificioEl.appendChild(zonaEl);
					gamaEl.appendChild(edificioEl);
					listadoEl.appendChild(gamaEl);
					// Totales por Planta para la anterior Planta.
					crearTotalesPlanta(arrayTotalPlanta, doc, plantaEl);
					plantaEl = doc.createElement("PLANTA");
					plantaEl.setAttribute("dPlanta", laFila.getPlanta()
							.toString());
					// Inicializar valores
					arrayTotalPlanta = new Integer[54];

					// Totales por Zona para la anterior Zona.
					crearTotalesZona(arrayTotalZona, doc, zonaEl);
					zonaEl = doc.createElement("ZONA");
					zonaEl.setAttribute("dZona", laFila.getZona().toString());
					// Inicializar valores
					arrayTotalZona = new Integer[54];

					// Totales por Edificio para la anterior Edificio.
					crearTotalesEdificio(arrayTotalEdificio, doc, edificioEl);
					edificioEl = doc.createElement("EDIFICIO");
					edificioEl.setAttribute("dEdificio", laFila.getEdificio()
							.toString());
					// Inicializar valores
					arrayTotalEdificio = new Integer[54];

					// Totales por Gama para la anterior Gama.
					Element totalSemanas = null;
					for (int a = 0; a < 54; a++) {
						if (arrayTotalGama[a] != null && arrayTotalGama[a] > 0) {
							Element totalSemanaEl = doc
									.createElement("TOTALSEMANA");
							totalSemanaEl.setAttribute("numero", "" + a);

							totalSemanas = doc.createElement("valor");
							totalSemanas
									.appendChild(doc
											.createTextNode(valorEnHoras(arrayTotalGama[a])));
							totalSemanaEl.appendChild(totalSemanas);
							gamaEl.appendChild(totalSemanaEl);
						}
					}

					gamaEl = doc.createElement("GAMA");
					gamaEl.setAttribute("dGama", laFila.getGama().toString());

					// Inicializar valores
					arrayTotalGama = new Integer[54];

				}

				// Si es un nuevo edificio o nueva gama inicializar array
				// edificios
				if (!esPrimero
						&& (!edificio.equals(laFila.getEdificio().toString()) || !gama
								.equals(laFila.getGama().toString()))) {
					// Inicializar valores
					// arrayTotalEdificio = new Integer[54];
				}

				Element filaEl = doc.createElement("MAQUINA");

				operacionEl = doc.createElement("ID");
				operacionEl.appendChild(doc.createTextNode(laFila
						.getIdmaquina() == null ? "" : laFila.getIdmaquina()
						.toString()));
				filaEl.appendChild(operacionEl);

				operacionEl = doc.createElement("NOMBRE");
				operacionEl.appendChild(doc.createTextNode(laFila
						.getDescripcion() == null ? "" : laFila
						.getDescripcion()));
				filaEl.appendChild(operacionEl);

				operacionEl = doc.createElement("CODIGO");
				operacionEl.appendChild(doc.createTextNode(laFila
						.getCodigoMaq() == null ? "-" : laFila.getCodigoMaq()));
				filaEl.appendChild(operacionEl);

				// Añadir valores por semana
				// Añadimos los valores por semana
				Element semanasEl = null;
				for (int a = 0; a < 54; a++) {
					if ((laFila.getArraySemana()[a].length() > 0)) {
						Element semanaEl = doc.createElement("SEMANA");
						semanaEl.setAttribute("numero", "" + a);

						semanasEl = doc.createElement("valor");
						semanasEl.appendChild(doc.createTextNode(laFila
								.getArraySemana()[a].length() == 0 ? ""
								: valorEnHoras(Integer.parseInt(laFila
										.getArraySemana()[a]))));
						semanaEl.appendChild(semanasEl);
						filaEl.appendChild(semanaEl);
						plantaEl.appendChild(filaEl);
						String nTiempo = laFila.getArraySemana()[a].length() == 0 ? "0"
								: laFila.getArraySemana()[a].toString();
						// Se guardan en el array la suma de tiempos por semana
						arrayTotalGama[a] = arrayTotalGama[a] == null ? Integer
								.parseInt(nTiempo) : arrayTotalGama[a]
								+ Integer.parseInt(nTiempo);
						arrayTotalEdificio[a] = arrayTotalEdificio[a] == null ? Integer
								.parseInt(nTiempo) : arrayTotalEdificio[a]
								+ Integer.parseInt(nTiempo);
						arrayTotalZona[a] = arrayTotalZona[a] == null ? Integer
								.parseInt(nTiempo) : arrayTotalZona[a]
								+ Integer.parseInt(nTiempo);
						arrayTotalPlanta[a] = arrayTotalPlanta[a] == null ? Integer
								.parseInt(nTiempo) : arrayTotalPlanta[a]
								+ Integer.parseInt(nTiempo);

					}
				}

				// PlanAnualEdif.logger.info("1xml PlanAnualEdif: "
				// + nodeToString(listadoEl));
				gama = laFila.getGama().toString();
				edificio = laFila.getEdificio().toString();
				zona = laFila.getZona().toString();
				planta = laFila.getPlanta().toString();
				esPrimero = false;
			}
			// Para el último registro
			zonaEl.appendChild(plantaEl);
			edificioEl.appendChild(zonaEl);
			gamaEl.appendChild(edificioEl);

			// Totales por Planta para la anterior Planta.
			crearTotalesPlanta(arrayTotalPlanta, doc, plantaEl);

			// Totales por Zona para la anterior Zona.
			crearTotalesZona(arrayTotalZona, doc, zonaEl);

			// Totales por Edificio para la anterior Edificio.
			crearTotalesEdificio(arrayTotalEdificio, doc, edificioEl);

			// Totales por Gama para la anterior Gama.
			Element totalSemanas = null;
			for (int a = 0; a < 54; a++) {
				if (arrayTotalGama[a] != null && arrayTotalGama[a] > 0) {
					Element totalSemanaEl = doc.createElement("TOTALSEMANA");
					totalSemanaEl.setAttribute("numero", "" + a);

					totalSemanas = doc.createElement("valor");
					totalSemanas.appendChild(doc
							.createTextNode(valorEnHoras(arrayTotalGama[a])));
					totalSemanaEl.appendChild(totalSemanas);
					gamaEl.appendChild(totalSemanaEl);
				}
			}

			listadoEl.appendChild(gamaEl);
			rootElement.appendChild(listadoEl);

		} catch (Exception e) {
			PlanAnualEdif.logger.info("eror xml PlanAnualEdif: ");
		}
		// PlanAnualEdif.logger.info("xml PlanAnualEdif: "
		// + nodeToString(rootElement));

		return doc;

	}

	private String valorEnHoras(Integer minutos) {
		String horas = "";
		String min = "";
		if (minutos != null) {
			horas = (minutos / 60 > 0 ? (minutos / 60) + "h " : "");
			min = (minutos % 60) > 0 ? minutos % 60 + "'" : "";
			return horas + min;
		} else {
			return "";
		}

	}

	private void crearTotalesPlanta(Integer[] arrayTotalPlanta, Document doc,
			Element plantaEl) {
		// Totales por Planta para la anterior Planta.
		Element totalPlantas = null;
		for (int a = 0; a < 54; a++) {
			if (arrayTotalPlanta[a] != null && arrayTotalPlanta[a] > 0) {
				Element totalPlantaEl = doc.createElement("TOTALPLANTA");
				totalPlantaEl.setAttribute("numero", "" + a);

				totalPlantas = doc.createElement("valor");
				totalPlantas.appendChild(doc
						.createTextNode(valorEnHoras(arrayTotalPlanta[a])));
				totalPlantaEl.appendChild(totalPlantas);
				plantaEl.appendChild(totalPlantaEl);
			}
		}
	}

	private void crearTotalesZona(Integer[] arrayTotalZona, Document doc,
			Element zonaEl) {
		// Totales por Zona para la anterior Zona.
		Element totalZonas = null;
		for (int a = 0; a < 54; a++) {
			if (arrayTotalZona[a] != null && arrayTotalZona[a] > 0) {
				Element totalZonaEl = doc.createElement("TOTALZONA");
				totalZonaEl.setAttribute("numero", "" + a);

				totalZonas = doc.createElement("valor");
				totalZonas.appendChild(doc
						.createTextNode(valorEnHoras(arrayTotalZona[a])));
				totalZonaEl.appendChild(totalZonas);
				zonaEl.appendChild(totalZonaEl);
			}
		}
	}

	private void crearTotalesEdificio(Integer[] arrayTotalEdificio,
			Document doc, Element edificioEl) {
		// Totales por Edificio para la anterior Edificio.
		Element totalEdificios = null;
		for (int a = 0; a < 54; a++) {
			if (arrayTotalEdificio[a] != null && arrayTotalEdificio[a] > 0) {
				Element totalEdificioEl = doc.createElement("TOTALEDIFICIO");
				totalEdificioEl.setAttribute("numero", "" + a);

				totalEdificios = doc.createElement("valor");
				totalEdificios.appendChild(doc
						.createTextNode(valorEnHoras(arrayTotalEdificio[a])));
				totalEdificioEl.appendChild(totalEdificios);
				edificioEl.appendChild(totalEdificioEl);
			}
		}

	}

	@SuppressWarnings("unused")
	private String nodeToString(Node node) {// element

		StringWriter sw = new StringWriter();

		try {

			Transformer t = TransformerFactory.newInstance().newTransformer();

			t.setOutputProperty(OutputKeys.ENCODING, "ISO-8859-1");

			t.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no");

			t.setOutputProperty(OutputKeys.INDENT, "yes");

			t.transform(new DOMSource(node), new StreamResult(sw));

		} catch (TransformerException te) {

		}

		return sw.toString();

	}

}
