/*
 * $Id: SoExcelDocConverter.java,v 1.9 2006/06/06 20:36:04 marbobo Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: SoExcelDocConverter.java,v $
 * Revision 1.9  2006/06/06 20:36:04  marbobo
 * + Mögliche NPE abgefangen
 *
 * Revision 1.8  2006/04/04 07:49:55  korowa
 * Konvertierung ins PDF-Format hinzugefügt.Nur erlaubte Konvertierungen werden durchgeführt(DocConverter:conversions).
 *
 * Revision 1.7  2006/03/23 11:36:43  marbobo
 * + Mögliche NPE abgefangen
 *
 * Revision 1.6  2006/03/10 09:05:07  korowa
 * +PowerPoint Presentationen können jetzt von OpenOffice konvertiert werden
 *
 * Revision 1.5  2004/11/10 15:02:43  koppy
 * Projektweite Überarbeitung von Error-Logs, Stacktraces,..
 *
 * Revision 1.4  2004/06/27 17:12:47  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.3  2003/11/29 22:13:53  koppy
 * InputStreams in VKCInputStream gekappselt
 *
 * Revision 1.2  2003/09/11 08:27:24  lawern
 * einige Methoden public gemacht
 *
 * Revision 1.1  2003/07/28 11:52:50  lawern
 * initiale Version
 *
 *
 */
package vkc.converter;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;

import vkc.misc.VKCLogManager;
import vkc.util.FileUtils;
import vkc.util.VKCInputStream;
import vkc.util.ZipUtils;

/**
 * Klasse zum Konvertieren von Textdokumenten.
 *
 * @author lawern
 */
public class SoExcelDocConverter extends DocConverter {
	private static final boolean debug = false;

	public static String docSuffix = ".xls";

	private File pdfFile = null;

	private File zipFile = null;

	private String htmlFile = null;

	private File htmlDir = null;

	private HtmlDocConverter htmlConverter = null;

	public SoExcelDocConverter() {
	}

	/**
	 * Liefert den Suffix für temporäre Dateien zurück.
	 *
	 * @return docSuffix
	 */
	public String getDocSuffix() {
		return docSuffix;
	}

	/**
	 * Diese Methode konvertiert das übergebene Dokument in die in der
	 * Collection definierten Formate. Der Parameter conversions wird zur Zeit
	 * noch nicht ausgewertet.
	 *
	 * @param docFile URL des zu konvertierendes Dokument
	 * @param conversions Collection von VKCDocumentTypes welche die zu
	 *        erzeugenden Konvertierungen beschreibt.
	 */
	public void convert(URL docFile, Collection conversions) {
		if (debug) {
			System.out.println("SoExcelDocConverter: " + docFile);
		}

		InputStream docStream = null;
		File tmpFile = null;

		try {
			//Datei von Url in temporäre Datei schreiben
			docStream = docFile.openStream();
			tmpFile = File.createTempFile("ExcelDoc", ".xls");

			if (!debug) {
				tmpFile.deleteOnExit();
			}

			FileUtils.saveInputStream(tmpFile, docStream, true);
			FileUtils.closeInputStream(docStream);

			try {
				if (enableHtml || enableTdf) {
					htmlDir = File.createTempFile("ExcelDoc", "");
					htmlDir.delete();
					htmlDir.mkdir();

					if (!debug) {
						htmlDir.deleteOnExit();
					}
					htmlFile = htmlDir.getCanonicalPath() + File.separator + "index.html";
				}

				if (enablePdf) {
					pdfFile = File.createTempFile("index", ".pdf");

					if (!debug) {
						pdfFile.deleteOnExit();
					}
				}
			} catch (java.io.IOException ioe) {
				VKCLogManager.errorLog(this, "3", "Can't create temp-file.", ioe);
			}

			//Dokument konvertieren
			try {
				int formatsNumber = 0;
				
				if (enablePdf) {
					formatsNumber++;
				}
				
				if (enableHtml || enableTdf) {
					formatsNumber++;
				}
				
				int i = 0;
				String[] convertTypes = new String[formatsNumber];
				
				if (enableHtml || enableTdf) {
					convertTypes[i] = "HTML (StarCalc)";
					i++;
				}
				
				if (enablePdf) {
					convertTypes[i] = "calc_pdf_Export";
					i++;
				}
				
				i = 0;

				URL[] urls = new URL[formatsNumber];
				
				if (enableHtml || enableTdf) {
					urls[i] = new File(htmlFile).toURL();
					i++;
				}
				if (enablePdf) {
					urls[i] = pdfFile.toURL();
					i++;
				}

				new SOfficeDocConverter().convert(docFile, convertTypes, urls);
			} catch (IOException e1) {
				VKCLogManager.errorLog(this, "", e1.getMessage(), e1);
			}

			if (enableHtml || enableTdf) {
				FileUtils.deleteZeroByteFile(new File(htmlFile));
				
				if (!new File(htmlFile).exists()) {
					VKCLogManager.errorLog(this, "6", "HTML conversion not generated.");

					try {
						FileUtils.deleteDirectory(htmlDir);
					} catch (Exception ex) {
						VKCLogManager.errorLog(this, "", ex.getMessage(), ex);
					}
				} else {
					try {
						//Html-Version zusammenzipen
						zipFile = File.createTempFile("ExcelDoc", ".zip");

						if (!debug) {
							zipFile.deleteOnExit();
						}

						ZipUtils.zip(htmlDir, zipFile, true, htmlDir.getCanonicalPath() + File.separator);
					} catch (java.io.IOException ioe) {
						VKCLogManager.errorLog(this, "4", "Can't create temp-file.", ioe);
					}

					if (enableTdf) {
						//TDL-Stream erzeugen
						//Der übergeben null-Parameter muss später durch eine Collection ersetzt werden,
						//welche dafür sorgt, dass nur ein Tdf-Stream erzeugt wird!!!
						htmlConverter = new HtmlDocConverter();
						htmlConverter.convert(new File(htmlFile).toURL(), null);
					}
					
					//Html-Verzeichnis löschen
					try {
						FileUtils.deleteDirectory(htmlDir);
					} catch (Exception ex) {
						VKCLogManager.errorLog(this, "5", "Can't delete temp-dir.", ex);
					}
				}
			}
		} catch (IOException ioe) {
			if (tmpFile != null) {
				VKCLogManager.errorLog(this, "8", "Can't create temp-file: " + tmpFile.getPath(), ioe);
			} else {
				VKCLogManager.errorLog(this, "8", "Can't create temp-file: ", ioe);
			}

			FileUtils.closeInputStream(docStream);
		} finally {
			//temporäre Dokumentendatei löschen
			if (!debug) {
				if (tmpFile != null) {
					tmpFile.delete();
				}
			}
		}
	}

	/**
	 * Liefert nach dem Aufruf der convert-Methode den Stream der
	 * Tdf-Konvertierung.
	 *
	 * @return Stream der Tdf-Konvertierung oder <code>null</code> falls er
	 *         nicht existiert
	 */
	public VKCInputStream getTdfStream() {
		if (htmlConverter != null && enableTdf) {
			return htmlConverter.getTdfStream();
		}

		return null;
	}

	/**
	 * Liefert nach dem Aufruf der convert-Methode den Stream der
	 * HTML-Konvertierung.
	 *
	 * @return Stream der HTML-Konvertierung oder <code>null</code> falls er
	 *         nicht existiert
	 */
	public VKCInputStream getHtmlStream() {
		if (zipFile != null && enableHtml) {
			incOpenStreams();

			try {
				return new VKCInputStream(new BufferedInputStream(new FileInputStream(zipFile)), zipFile.length()) {
					public void close() throws IOException {
						super.close();
						closeHtmlStream();
					}
				};
			} catch (Exception e) {
				VKCLogManager.errorLog(this, "2", "ZIP-File not found!", e);
			}
		}

		return null;
	}

	/**
	 * Liefert nach dem Aufruf der convert-Methode den Stream der
	 * PDF-Konvertierung.
	 *
	 * @return Stream der PDF-Konvertierung oder <code>null</code> falls er
	 *         nicht existiert
	 */
	public VKCInputStream getPdfStream() {
		if (pdfFile != null && enablePdf) {
			incOpenStreams();

			try {
				return new VKCInputStream(new BufferedInputStream(new FileInputStream(pdfFile)), pdfFile.length()) {
					public void close() throws IOException {
						super.close();
						closePdfStream();
					}
				};
			} catch (Exception e) {
				VKCLogManager.errorLog(this, "1", "PDF-File not found!", e);
			}
		}

		return null;
	}

	void closePdfStream() {
		if (debug) {
			System.out.println("closePdfStream");
		}

		decOpenStreams();
	}

	/**
	 * Gibt eine Liste zurueck, der alle HREFs einer Seite enthält.
	 *
	 * @return Link-Vektor
	 */
	public ArrayList getLinks() {
		if (htmlConverter != null) {
			return htmlConverter.getLinks();
		}

		return null;
	}

	/**
	 * Liefert den Titel des Dokuments zurück.
	 *
	 * @return Titel des Dokuments oder <code>null</code>
	 */
	public String getTitle() {
		if (htmlConverter != null) {
			return htmlConverter.getTitle();
		}

		return null;
	}

	/**
	 * Liefert eine Collection mit Objekten vom Typ TdfElement zurück, welche
	 * das Dokument beschreiben.
	 *
	 * @return Collection mit Objekten vom Typ TdfElement
	 */
	public Collection getElements() {
		if (htmlConverter != null) {
			return htmlConverter.getElements();
		}

		return null;
	}

	/**
	 * Löschen der TDF-Streams
	 */
	void closeTdfStream() {
		if (debug) {
			System.out.println("closeTdfStream");
		}

		decOpenStreams();
	}

	/**
	 * Löschen des Html-Streams
	 */
	void closeHtmlStream() {
		if (debug) {
			System.out.println("closeHtmlStream");
		}

		decOpenStreams();

		//ZIP-Datei löschen
		if (zipFile != null) {
			zipFile.delete();
		}
	}

	/**
	 * Schließt das Konverter-Objekt und fügt es wieder in den Konverter-Pool
	 * ein.
	 */
	final void closeConverter() {
		//temporäre Dateien löschen
		if (zipFile != null) {
			zipFile.delete();
		}
		//this-Referenz wieder in die Queue einfügen
	}
}