/*
 * $Id: HttpDocToZipFile.java,v 1.6 2004/08/27 16:30:25 koppy Exp $
 *
 * Copyright (c) Siemens AG 2008 
 *           (c) Universität Paderborn 2008 
 * Licensed under EUPL 1.1. 
 *
 * $Log: HttpDocToZipFile.java,v $
 * Revision 1.6  2004/08/27 16:30:25  koppy
 * Unterstützung für CGI-Urls hinzugefügt
 *
 * Revision 1.5  2004/06/27 17:33:37  marbobo
 * + Quellcode maintenance
 *
 * Revision 1.4  2003/07/29 23:08:46  koppy
 * + rootFilename  in HttpDocToZipFile
 *
 * Revision 1.3  2003/07/02 13:16:27  koppy
 * +Berechnung der Dokumentgröße
 *
 * Revision 1.2  2003/07/02 13:14:09  koppy
 * WebCopy-SS verbessert zwecks 'docSize'
 *
 * Revision 1.1  2003/06/17 16:00:52  koppy
 * Initiale Version
 *
 */
package vkc.util.webcopy;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import net.matuschek.http.DocManagerException;
import net.matuschek.http.HttpDoc;
import net.matuschek.http.HttpDocToFile;
import net.matuschek.spider.WebRobotCallback;
import vkc.util.FileUtils;

/**
 * DocumentManager that will store document contents in a single ZIP file.
 *
 * @author koppy
 */
public class HttpDocToZipFile
	extends HttpDocToFile
	implements WebRobotCallback {

	private BufferedOutputStream bOut = null;
	private ZipOutputStream zipOut = null;
	private String zipFileName = null;
	private int fileSize = -1;
	private int docCount = 0;
	private String rootFilename;

	/**
	 * creates a new HttpDocToFile object that will store the documents in the
	 * given directory
	 */
	public HttpDocToZipFile() throws IOException {
		super("c:/temp");

		File tmpFile = File.createTempFile("tmpWebDoc", ".zip");
		tmpFile.deleteOnExit();

		super.setBaseDir(tmpFile.getParentFile().getAbsolutePath());
		zipFileName = tmpFile.getName();

	}

	/**
	 * creates a new HttpDocToFile object that will store the documents in the
	 * given directory
	 */
	public HttpDocToZipFile(String baseDir) {
		this(baseDir, "index.zip");

	}

	/**
	 * creates a new HttpDocToFile object that will store the documents in the
	 * given directory
	 */
	public HttpDocToZipFile(String baseDir, String zipFileName)	{
		super(baseDir);

		this.zipFileName = zipFileName;

	}

	/**
	 * Returns the corresponding zipFile for this URL
	 *
	 * @param url for this URL
	 */
	public File getZipFile() {

		return new File(new File(this.getBaseDir()), zipFileName);
	}

	/**
	 * These method is called if the WebRobot has finished its work
	 */
	public void webRobotDone() {
		FileUtils.closeOutputStream(zipOut);
		FileUtils.closeOutputStream(bOut);
	}

	/**
	 * store document (that means write it to a zip file)
	 *
	 * @param doc the document to store
	 *
	 * @exception DocManagerException if the document can't be stored (some IO
	 *            error occured)
	 */
	public void processDocument(HttpDoc doc) throws DocManagerException {
		if (doc == null) {
			return;
		}

		if ((!this.getStoreCGI())
			&& (doc.getURL().toString().indexOf('?') >= 0)) {
			// do not store dynamic pages, because storeCGI is false
			// and the URL contains a "?"
			return;
		}

		String filename = url2Filename(doc.getURL());
		if( docCount == 1 ){
			this.rootFilename = new String(filename).replace('\\', '/');
		}		

		if (doc.getContent().length >= this.getMinFileSize()) {
			try {
				if (zipOut == null) {
					bOut =
						new BufferedOutputStream(new FileOutputStream(getZipFile()));
					zipOut = new ZipOutputStream(bOut);
				}

				ZipEntry entry = new ZipEntry(filename);
				zipOut.putNextEntry(entry);

				byte[] content = doc.getContent();
				zipOut.write(content, 0, content.length);

				zipOut.closeEntry();
				zipOut.flush();
			} catch (Exception e) {
				throw new DocManagerException(e.getMessage());
			}
		}
	}

	/**
	 * converts an URL to a filename http://host/path will be converted to path
	 *
	 * @param url a URL to convert, must not be null
	 *
	 * @return converted URL
	 */
	protected String url2Filename(URL url) {
		
	    String filename = super.url2Filename(url);
		filename = filename.substring(
			this.getBaseDir().length() + url.getHost().length() + 2);
		
		int qIndex = filename.indexOf( File.pathSeparator + "?");
		if(  qIndex > -1)
		    return filename.substring(0, qIndex + 1 )+ "index.html";
	
		qIndex = filename.indexOf('?');
		if(  qIndex == 0)
		    return "index.html";
		else if ( qIndex > 0 )
		    return filename.substring(0, qIndex );
		
		return filename;
	}
	

	/**
	 * Gets a document that was stored previous from the file system. Because
	 * the HttpDocToZipFile does not store the HTTP headers, only the
	 * Content-Type header will exists. Even this header may not be correct.
	 * It will only use a simple heuristic to determine the possible MIME
	 * type.
	 *
	 * @return null, if this document was not stored before or it seems to be a
	 *         dynamic document.
	 */
	public HttpDoc retrieveFromCache(URL u) {
		return null;
	}

	// Ignore these WebRobotCallBack Methods
	public void webRobotRetrievedDoc(String url, int size) {
		this.docCount++;
		this.fileSize += size;
	}
	public void webRobotUpdateQueueStatus(int length) {
	}
	public void webRobotSleeping(boolean sleeping) {
	}

	/**
	 * Gets the size of this main document
	 * @return size of this main document
	 */
	public int getFileSize() {
		return fileSize;
	}

	/**
	 * Returns the number of Documents
	 * 
	 * @return number of processed documents
	 */
	public int getDocCount() {
		return docCount;
	}

	/**
	 * Returns the root filename
	 * 
	 * @return the root filename
	 */
	public String getRootFilename(){
		return this.rootFilename;
	}
}