//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.layout;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.eclipse.epf.common.utils.I18nUtil;
import org.eclipse.epf.common.utils.Timer;
import org.eclipse.epf.common.xml.XSLTProcessor;
import org.eclipse.epf.library.ILibraryResourceManager;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.LibraryResources;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.layout.util.XmlHelper;
import org.eclipse.epf.library.prefs.PreferenceUtil;
import org.eclipse.epf.library.util.ContentResourceScanner;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.uma.MethodElement;

import com.ibm.icu.util.Calendar;


/**
 * Generates the HTML page for a Method element.
 * 
 * @author Jinhua Xi
 * @author Kelvin Low
 * @since 1.0
 */
public class HtmlBuilder {

	private boolean debug = false;

	private Properties xslParams = null;

	private ElementLayoutManager mgr = null;

	private ElementLayoutManager internal_mgr = null;

	//private ContentResourceScanner scanner = null;

	private boolean scanContent = true;

	// If true, display the "Show tree browse" image/link to the right of a
	// published page.
	private boolean showTreeBrowser = false;

	//private IContentValidator validator = null;

	// override this path to specify xsl path
	private String layoutXslRootPath = LibraryPlugin.getDefault().getLayoutXslPath();
	
	/**
	 * Creates a new instance.
	 */
	public HtmlBuilder() {
		this(null);
	}

	/**
	 * Creates a new instance.
	 */
	public HtmlBuilder(ElementLayoutManager mgr) {
		init();
		setLayoutManager(mgr);
	}
	
	public void setLayoutXslRootPath(String path) {
		try {
			if ( path != null && path.length() > 0 ) {
				this.layoutXslRootPath = path;
				if ( !this.layoutXslRootPath.endsWith(File.separator) ) {
					this.layoutXslRootPath += File.separator;
				}
				
				// get the localized file
				File file = new File(this.layoutXslRootPath, "resources.properties"); //$NON-NLS-1$
				Locale locale = Locale.getDefault();
				String localFileName = I18nUtil.getLocalizedFile(file.getAbsolutePath(), locale);
				if ( localFileName != null ) {
					file = new File(localFileName);
				}
				if (file.exists()) {
					xslParams.load(new FileInputStream(file));
				}	
				
				// the PreferenceUtil also uses the xsl properties for activity breakdown layout
				// so set it as well
				PreferenceUtil.setXslProperties(xslParams);
			}
		} catch (IOException e) {
		}
	}
	
	/**
	 * Performs the necessary initialization.
	 */
	protected void init() {
		debug = LibraryPlugin.getDefault().isDebugging();
		loadDefaultLayoutXsl();
	}

	public void loadDefaultLayoutXsl() {
		layoutXslRootPath = LibraryPlugin.getDefault().getLayoutXslPath();
		try {
			xslParams = LibraryPlugin.getDefault().getProperties(
					"/layout/xsl/resources.properties"); //$NON-NLS-1$
			
			// add the colon property, 
			xslParams.put("colon_with_space", LibraryResources.colon_with_space); //$NON-NLS-1$
			
			// the PreferenceUtil also uses the xsl properties for activity breakdown layout
			// so set it as well
			PreferenceUtil.setXslProperties(xslParams);

			
		} catch (IOException e) {
			xslParams = null;
		}
	}
	
	/**
	 * Returns the publish directory.
	 */
	public String getPublishDir() {
		return (mgr == null) ? null : mgr.getPublishDir();
	}

	/**
	 * Returns the publish directory.
	 */
	public void setPublishDir(String dir) {
		if (mgr != null) {
			mgr.setPublishDir(dir);
		}

		//getScanner().setTargetRootPath(new File(getPublishDir()));

		// Reset the validator's publish dir.
		getValidator().setPublishDir(dir);
	}

//	/**
//	 * Sets the content validator.
//	 */
//	public void setValidator(IContentValidator validator) {
//		this.validator = validator;
//		getScanner().setValidator(this.validator);
//	}

	/**
	 * Returns the content validator.
	 */
	public IContentValidator getValidator() {
//		if (validator == null) {
//			validator = new DefaultContentValidator(getPublishDir());
//		}
//		return validator;
		
		return this.mgr.getValidator();
	}

	/**
	 * Returns the content resource scanner for the element.
	 */
	private ContentResourceScanner getScanner(MethodElement owner) {
		ILibraryResourceManager resMgr = ResourceHelper.getResourceMgr(owner);
		if ( resMgr == null ) {
			return null;
		}
		
		String rootContentPath = resMgr.getLogicalPluginPath(owner);
		File src_root = new File(resMgr.getPhysicalPluginPath(owner));
		File tgt_root = new File(getPublishDir(), rootContentPath);
		ContentResourceScanner scanner = new ContentResourceScanner(src_root, tgt_root, rootContentPath, getValidator());

		return scanner;
	}

	/**
	 * Sets the flag to display the "Show tree browser" image/link.
	 */
	public void enableTreeBrowser(boolean flag) {
		this.showTreeBrowser = flag;
	}

	/**
	 * Enables content scanning.
	 */
	public void enableContentScan(boolean scan) {
		this.scanContent = scan;
	}

	/**
	 * Returns <code>true</code> if content scanning is enabled.
	 */
	public boolean contentScanEnabled() {
		return scanContent;
	}

	/**
	 * Sets the Element Layout Manager.
	 * <p>
	 * A Element Layout Manager is associated with a configuration.
	 */
	public void setLayoutManager(ElementLayoutManager mgr) {
		this.mgr = mgr;
		if (this.mgr == null) {
			this.mgr = getDefaultLayoutManager(); 
		}

		// Update the scanner target path.
		//getScanner().setTargetRootPath(new File(getPublishDir()));

		// Reset the validator pub dir.
		getValidator().setPublishDir(getPublishDir());
	}

	/**
	 * Returns the default Element Layout Manager.
	 */
	private ElementLayoutManager getDefaultLayoutManager() {
		if ( this.internal_mgr == null ) {
			this.internal_mgr = new ElementLayoutManager();
		}
		
		return this.internal_mgr;
	}

	/**
	 * Returns the Element Layout Manager.
	 */
	public ElementLayoutManager getLayoutManager() {
		if (this.mgr == null) {
			this.mgr = getDefaultLayoutManager();
		}
		return mgr;
	}

	/**
	 * Generates the HTML for a Method element.
	 * 
	 * @param element
	 *            A Method element.
	 * @return A url of the generated content HTML file.
	 */
	public String generateHtml(MethodElement element) {
		String url = null;
		if (debug) {
			long startTime = System.currentTimeMillis();
			IElementLayout layout = getLayoutManager().getLayout(element, true);
			url = generateHtml(layout);
			long endTime = System.currentTimeMillis();
			System.out
					.println("Time taken to render HTML page for " + element.getName() + //$NON-NLS-1$
							": " + (endTime - startTime) + " ms"); //$NON-NLS-1$ //$NON-NLS-2$
		} else {
			IElementLayout layout = getLayoutManager().getLayout(element, true);
			url = generateHtml(layout);
		}
		return url;
	}


	/**
	 * Generates the HTML for a Method element.
	 * 
	 * @param url
	 *            The URL of a Method element.
	 */
	public void generateHtml(String url) {
		IElementLayout layout = getLayoutManager().getLayout(url);
		generateHtml(layout);
	}

	/**
	 * Generates the HTML for a Method element.
	 * 
	 * @param layout
	 *            A Method Element. Layout object.
	 * @param linkedElements
	 *            If not null, this object will be populated with a list of
	 *            linked elements in the page.
	 * @return A url of the generated content HTML file.
	 */
	public String generateHtml(IElementLayout layout) {
		if (layout == null) {
			return "about:blank"; //$NON-NLS-1$
		}

		//System.out.println("*** generateHtml: " + LibraryUtil.getTypeName(layout.getElement()) );
		
		// add time logging when publishing element
		long time_start = Calendar.getInstance().getTimeInMillis();
		String elementPath = layout.getFilePath().replace('/',
				File.separatorChar);
		String elementPathName = elementPath
				+ layout.getFileName(ResourceHelper.FILE_EXT_HTML);
		String filePath = this.getPublishDir() + elementPath;
		String html_file = this.getPublishDir() + elementPathName;

		try {

			StringBuffer xml = getXml(layout);

			String xsl_uri;

			File f = new File(filePath);
			if (!f.exists()) {
				f.mkdirs();
			}

			// Generate the additonal outputs.
			List layouts = layout.getLayouts();
			xsl_uri = layoutXslRootPath + layout.getXslUrl();
			generateHtml(layout, xsl_uri, html_file, xml);

			// Generate other layout files.
			if (layouts != null && layouts.size() > 0) {
				for (Iterator it = layouts.iterator(); it.hasNext();) {
					LayoutInfo info = (LayoutInfo) it.next();
					xsl_uri = layoutXslRootPath + info.layout_xsl;
					String file = filePath + info.fileName;
					generateHtml(layout, xsl_uri, file, xml);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
			html_file = null;
		}

		long time_end = Calendar.getInstance().getTimeInMillis();
		long mini_seconds = time_end - time_start;
		if (mini_seconds > 1000) {
			String msg = mini_seconds
					+ " mini-second(s) publishing element " + LibraryUtil.getTypeName(layout.getElement()) + "[" + elementPathName + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			IContentValidator validator = getValidator();
			if (validator == null) {
				System.out.println(msg);
			} else {
				validator.logInfo(msg);
			}
		}
		if (html_file != null) {
			return html_file;
		}

		return "about:blank"; //$NON-NLS-1$
	}

	/**
	 * Generates the HTML for a Method element.
	 * 
	 * @param layout
	 *            A Method Element. Layout object.
	 * @param xslURI
	 *            The XSL stylesheet.
	 * @param htmlFile
	 *            The HTML file to be generated.
	 * @param xml
	 *            The XML buffer.
	 * @return A url of the generated content HTML file.
	 */
	private void generateHtml(IElementLayout layout,
			String xsl_uri, String html_file, StringBuffer xml) {
		Throwable th = null;
		if (layout == null) {
			return;
		}

		Timer timer = null;
		if ( debug ) {
			timer = new Timer();
		}
		
		try {
			StringWriter sw = new StringWriter();
			XSLTProcessor.transform(xsl_uri, xml.toString(), xslParams, sw);
			sw.flush();
			String content = sw.getBuffer().toString();

			if ( debug) {
				timer.stop();
				System.out.println(timer.getTime() + " mini seconds for xml/xslt transformation"); //$NON-NLS-1$
				timer.start();
			}
			// Always validate and fix the content before publishing.
			content = ResourceHelper.validateContent(layout.getElement(),
					content, getValidator(), layout.getLayoutMgr()
							.getConfiguration());
			if (contentScanEnabled()) {
				scanContentForResources(layout.getElement(), content, layout
						.getFilePath());
			}

			if ( debug) {
				timer.stop();
				System.out.println(timer.getTime() + " mini seconds scanning content"); //$NON-NLS-1$
				timer.start();
			}
			
			OutputStreamWriter output = new OutputStreamWriter(
					new FileOutputStream(html_file), "utf-8"); //$NON-NLS-1$
			output.write(content);
			output.flush();
			output.close();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			th = e;
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			th = e;
		} catch (IOException e) {
			e.printStackTrace();
			th = e;
		} catch (Exception e) {
			e.printStackTrace();
			th = e;
		}

		if (th != null) {
			this.getValidator().logError(layout.getElement(),
					"Error generating element content", th); //$NON-NLS-1$
		}
	}

	/**
	 * Generates the HTML for a Method element.
	 * 
	 * @param layout
	 *            A Method Element. Layout object.
	 * @return A url of the generated content HTML file.
	 */
	private StringBuffer getXml(IElementLayout layout) {
		StringBuffer xml = new StringBuffer();
		XmlElement xmlElement = layout.getXmlElement(true);
		
		// set the language attribute
		Locale locale = Locale.getDefault();
		String lang = locale.getLanguage();
		xmlElement.setAttribute("lang", lang); //$NON-NLS-1$

		if (showTreeBrowser) {
			xmlElement.setAttribute("showTreeBrowser", "true"); //$NON-NLS-1$ //$NON-NLS-2$
		}

		xml.append(XmlHelper.XML_HEADER).append(xmlElement.toXml());

		if ( debug ) {
			try {
				String xml_file = this.getPublishDir() + "xml" + File.separator; //$NON-NLS-1$
				xml_file += layout.getType() + "." + layout.getFileName(".xml"); //$NON-NLS-1$ //$NON-NLS-2$
				File xf = new File(xml_file);
				if ( !xf.exists() )
				{
					xf.getParentFile().mkdirs();
					xf.createNewFile();
				}
							
				OutputStreamWriter output = new OutputStreamWriter(
						new FileOutputStream(xf), "utf-8"); //$NON-NLS-1$
				output.write(xml.toString());
				output.flush();
				output.close();
	
				// FileWriter xw = new FileWriter(xml_file);
				// xw.write(xml.toString());
				// xw.flush();
				// xw.close();
			} catch (Exception ex) {
				ex.printStackTrace();
			}
		}
		
		return xml;
	}

	/**
	 * Scans the content for resource references.
	 */
	private void scanContentForResources(MethodElement owner, String content,
			String contentPath) {
		ContentResourceScanner scanner = getScanner(owner);
		if ( scanner != null ) {
			scanner.resolveResources(owner, content, contentPath);
		}
	}

	public void dispose() {
//		if (validator != null) {
//			validator.dispose();
//		}

		if ( internal_mgr != null ) {
			internal_mgr.clear();
			internal_mgr = null;
		}
		
		mgr = null;
//		scanner = null;
//		validator = null;
	}
}
