//------------------------------------------------------------------------------
// 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.publishing.services;

import java.io.File;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.epf.common.utils.Timer;
import org.eclipse.epf.library.layout.DefaultContentValidator;
import org.eclipse.epf.library.layout.LinkInfo;
import org.eclipse.epf.library.layout.util.XmlElement;
import org.eclipse.epf.library.util.LibraryUtil;
import org.eclipse.epf.library.util.ResourceHelper;
import org.eclipse.epf.publishing.PublishingPlugin;
import org.eclipse.epf.publishing.PublishingResources;
import org.eclipse.epf.publishing.util.http.HttpResponse;
import org.eclipse.epf.publishing.util.http.HttpUtil;
import org.eclipse.epf.uma.ContentCategory;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.MethodElement;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.util.Calendar;

/**
 * content validator used for publishing. This class will be responsible for validating the content to be published, 
 * fixing problems such as links in the content, 
 * and logging information about missing elements, missing resources, etc.
 * 
 * @author Jinhua Xi
 * @since 1.0
 * 
 */
public class PublishingContentValidator extends DefaultContentValidator {

	private boolean debug = PublishingPlugin.getDefault().isDebugging();

	//private boolean showExtraInfoForDescriptors = false;
	//private boolean showRelatedDescriptors = false;
	
	protected PublishHTMLOptions options = null;
	
	class InvalidExternalLinkInfo {
		public MethodElement owner;

		public String url;

		public String message;

		public InvalidExternalLinkInfo(MethodElement owner, String url,
				String message) {
			this.owner = owner;
			this.url = url;
			this.message = message;
		}
	}

	class MissingReference {
		public MethodElement owner;

		public MethodElement refElement;

		public String guid;

		public String linkedText;

		public MissingReference(MethodElement owner, MethodElement refElement) {
			this.owner = owner;
			this.refElement = refElement;
		}

		public MissingReference(MethodElement owner, String guid,
				String linkedText) {
			this.owner = owner;
			this.guid = guid;
			this.linkedText = linkedText;
		}
	}

	class MissingResource {
		public MethodElement owner;

		public File resourceFile;

		public String url;

		public MissingResource(MethodElement owner, File resourceFile,
				String url) {
			this.owner = owner;
			this.resourceFile = resourceFile;
			this.url = url;
		}
	}

	static final String LOGS_FOLDER = "logs"; //$NON-NLS-1$

	static final String ERROR_LOG_FILENAME = "error.log"; //$NON-NLS-1$

	static final String WARNING_LOG_FILENAME = "warning.log"; //$NON-NLS-1$

	static final String INFO_LOG_FILENAME = "info.log"; //$NON-NLS-1$

	protected File logPath;

	protected boolean validateExternalLinks = false;

	protected List invalidExternalLinks = new ArrayList();

	// cache the valided external links to avoid multiple checking
	protected List validatedExternalLinks = new ArrayList();

	protected List missingReferences = new ArrayList();

	protected List missingResources = new ArrayList();

	protected List discardedElements = new ArrayList();

	protected List validCategories = new ArrayList();

	protected long publishing_start = 0;

	protected long time_for_external_link_checking = 0;

	// collect the elements referenced by the published contents so we can
	// publish them
	// this will be the elements to be published
	protected List referencedElements = new ArrayList();

	// published elements
	protected List publishedElements = new ArrayList();

	// this is the default target element for the content validator
	// set this before publishing the element and set to null after the
	// publishign is done
	protected MethodElement defaultTarget = null;

	/**
	 * consructor
	 * 
	 * @param pubDir String
	 * @param validateExternalLinks boolean
	 */
	public PublishingContentValidator(String pubDir, PublishHTMLOptions options) {
		super(pubDir);
		this.options = options;
		
		this.validateExternalLinks = options.isCheckExternalLinks();

		this.logPath = new File(pubDir, LOGS_FOLDER);
		super.info = getStream(INFO_LOG_FILENAME);
		super.warning = getStream(WARNING_LOG_FILENAME);
		super.error = getStream(ERROR_LOG_FILENAME);

		// set the start time
		publishing_start = Calendar.getInstance().getTimeInMillis();
	}

	/**
	 * dispose the object
	 */
	public void dispose() {
		invalidExternalLinks.clear();
		validatedExternalLinks.clear();
		missingReferences.clear();
		missingResources.clear();
		discardedElements.clear();
		validCategories.clear();

		referencedElements.clear();
		publishedElements.clear();

		info.close();
		warning.close();
		error.close();

	}

	protected PrintStream getStream(String fileName) {
		try {
			File f = new File(logPath, fileName);
			File dir = f.getParentFile();
			dir.mkdirs();

			if (!f.exists()) {
				f.createNewFile();
			}

			return new PrintStream(new FileOutputStream(f), true);
		} catch (Exception e) {

		}

		return null;
	}

	/**
	 * validate the link attributes fro the element.
	 * 
	 * @param owner MethodElement the owner element
	 * @param attributes String the attributes in the link
	 * @param text String the text allow with the link
	 * @param config MethodConfiguration 
	 * 
	 * @return LinkInfo
	 */
	public LinkInfo validateLink(MethodElement owner, String attributes,
			String text, MethodConfiguration config, String tag) {
		LinkInfo info = super.validateLink(owner, attributes, text, config, tag);

		if (validateExternalLinks) {
			
			String url = info.getUrl();
			if ((url != null) && ResourceHelper.isExternalLink(url)
					&& !url.startsWith("ftp://")) //$NON-NLS-1$
			{
				if (!validatedExternalLinks.contains(url)) {
					Timer t = new Timer();
					try {
						HttpResponse resp = HttpUtil.doGet(url, null, 6000); // timeout
						// System.out
						// .println(time
						// + " mini-seconds querying Url '" + url + "', return
						// status=" + resp.getStatus()); //$NON-NLS-1$
						// //$NON-NLS-2$
					} catch (java.net.UnknownHostException e) {
						logInvalidExternalLink(owner, url, null);
					} catch (Exception e) {
						logInvalidExternalLink(owner, url, e.getMessage());
					}

					t.stop();
					time_for_external_link_checking += t.getTime();
					
					// cache it
					validatedExternalLinks.add(url);
					
					// do we need to log the info so that user know what external
					// urls are referenced in the content?
					logInfo(owner, NLS.bind(PublishingResources.externalUrl_msg,
							new Object[]{new Integer(t.getTime()), url}));
				}

			}			
		}
		return info;
	}

	/**
	 * log missing reference.
	 * @param owner MethodElement
	 * @param refElement MethodElement the missing element
	 */
	public void logMissingReference(MethodElement owner,
			MethodElement refElement) {
		super.logMissingReference(owner, refElement);
		missingReferences.add(new MissingReference(owner, refElement));
	}

	/**
	 * log missing reference
	 * @param owner M<ethodElement
	 * @param guid String the guid of the missing element
	 * @param linkedText String the linked text. 
	 */
	public void logMissingReference(MethodElement owner, String guid,
			String linkedText) {
		super.logMissingReference(owner, guid, linkedText);
		missingReferences.add(new MissingReference(owner, guid, linkedText));
	}

	/**
	 * log missing resource.
	 * 
	 * @param owner MethodElement
	 * @param resourceFile File
	 * @param url String
	 */
	public void logMissingResource(MethodElement owner, File resourceFile,
			String url) {
		super.logMissingResource(owner, resourceFile, url);
		missingResources.add(new MissingResource(owner, resourceFile, url));
	}

	/**
	 * log invalid external link
	 * @param owner
	 * @param url String
	 * @param message String
	 */
	public void logInvalidExternalLink(MethodElement owner, String url,
			String message) {
		super.logInvalidExternalLink(owner, url, message);
		invalidExternalLinks.add(new InvalidExternalLinkInfo(owner, url,
				message));
	}

	/**
	 * get report about the content validation.
	 * 
	 * @return XmlElement
	 */
	public XmlElement getReport() {
		XmlElement reportXml = new XmlElement("validatorInfo"); //$NON-NLS-1$

		if (invalidExternalLinks.size() > 0) {
			String msg = time_for_external_link_checking / 1000
			+ " seconds validating external links"; //$NON-NLS-1$
			System.out.println(msg);
			logInfo(msg);

			XmlElement invalidExternalLinksXml = reportXml
					.newChild("invalidExternalLinks"); //$NON-NLS-1$
			for (Iterator it = invalidExternalLinks.iterator(); it.hasNext();) {
				InvalidExternalLinkInfo info = (InvalidExternalLinkInfo) it
						.next();
				invalidExternalLinksXml.newChild("entry") //$NON-NLS-1$
						.setAttribute("url", info.url) //$NON-NLS-1$
						.setAttribute(
								"owner", (info.owner == null) ? "" : LibraryUtil.getLocalizeTypeName(info.owner)) //$NON-NLS-1$ //$NON-NLS-2$
						.setAttribute("message", info.message); //$NON-NLS-1$
			}
		}

		if (missingReferences.size() > 0) {
			XmlElement invalidReferencesXml = reportXml
					.newChild("invalidReferences"); //$NON-NLS-1$
			XmlElement missingReferencesXml = reportXml
					.newChild("missingReferences"); //$NON-NLS-1$
			for (Iterator it = missingReferences.iterator(); it.hasNext();) {
				MissingReference info = (MissingReference) it.next();
				if (info.refElement == null) {
					invalidReferencesXml
							.newChild("entry") //$NON-NLS-1$
							.setAttribute("element", info.linkedText) //$NON-NLS-1$
							.setAttribute("guid", info.guid) //$NON-NLS-1$
							.setAttribute(
									"owner", (info.owner == null) ? "" : LibraryUtil.getLocalizeTypeName(info.owner)); //$NON-NLS-1$ //$NON-NLS-2$
				} else {
					missingReferencesXml
							.newChild("entry") //$NON-NLS-1$
							.setAttribute(
									"element", (info.refElement == null ) ? "" : LibraryUtil.getLocalizeTypeName(info.refElement)) //$NON-NLS-1$ //$NON-NLS-2$
							.setAttribute("guid", info.refElement.getGuid()) //$NON-NLS-1$
							.setAttribute(
									"owner", (info.owner == null) ? "" : LibraryUtil.getLocalizeTypeName(info.owner)); //$NON-NLS-1$ //$NON-NLS-2$
				}
			}
		}

		if (missingResources.size() > 0) {
			XmlElement missingResourcesXml = reportXml
					.newChild("missingResources"); //$NON-NLS-1$
			for (Iterator it = missingResources.iterator(); it.hasNext();) {
				MissingResource info = (MissingResource) it.next();
				missingResourcesXml
						.newChild("entry") //$NON-NLS-1$
						.setAttribute("url", info.url) //$NON-NLS-1$
						.setAttribute(
								"resource", (info.resourceFile == null) ? "" : info.resourceFile.getPath()) //$NON-NLS-1$ //$NON-NLS-2$
						.setAttribute(
								"owner", (info.owner == null) ? "" : LibraryUtil.getLocalizeTypeName(info.owner)); //$NON-NLS-1$ //$NON-NLS-2$

			}
		}

		long publishing_time = (Calendar.getInstance().getTimeInMillis() - publishing_start) / 1000;
		int minutes = (int) publishing_time / 60;
		int seconds = (int) publishing_time - minutes * 60;

		logInfo("Publishing time: " + minutes + " minutes " + seconds + " seconds"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

		return reportXml;
	}

	/**
	 * add a category that should be published.
	 * 
	 * @param e ContentCategory
	 */
	public void addValidCategory(ContentCategory e) {
		if (!validCategories.contains(e)) {
			validCategories.add(e);
		}
	}

	/**
	 * check if the element is discarded or not discarded elements will be
	 * treated as out side the configursation
	 * 
	 * @param owner
	 *            MethodElement the owner of the element
	 * @param feature 
	 * 			  Object EStructuralFeature or OppositeFeature
	 * @param e
	 *            MethodElement the element to be checked
	 *            
	 * @return boolean
	 */
	public boolean isDiscarded(MethodElement owner, Object feature,
			MethodElement e) {
		if (discardedElements.contains(e)) {
			return true;
		}

		// if the element is a ContentCategory and is not discarded
		if (e instanceof ContentCategory) {
			if (validCategories.contains(e)) {
				return false;
			}

			// otherwise, check if it should be discarded or not
			// TODO
			// for now, discard all referenced content categories if they are
			// not included in the publishing view.
			// NO!!!!!!!!!!!! This will lead to a lot of broken links and
			// missing element
			// TOO strong limitation. Let open it for now
			// Publishing:Overview page in published website
			// have broken links to BM
			// return true;
			return false;
		}
		return false;
	}

	/**
	 * add a referenced element
	 * 
	 * @param owner MethodElement
	 * @param e MethodElement
	 */
	public void addReferencedElement(MethodElement owner, MethodElement e) {
		if (e == null) {
			return;
		}

		// don't add discarded elements
		if (isDiscarded(owner, null, e)) {
			if (debug) {
				System.out
						.println("Element is discarded: " + LibraryUtil.getLocalizeTypeName(e)); //$NON-NLS-1$
			}
			return;
		}

		if (e != null && !referencedElements.contains(e)
				&& !publishedElements.contains(e)) {
			referencedElements.add(e);
			logReference(owner, e);
		}
	}

	/**
	 * log a refernece
	 * 
	 * @param owner MethodElement
	 * @param e MethodElement
	 */
	public void logReference(MethodElement owner, MethodElement e) {
		if (debug) {
			System.out
					.println("--- Referenece Element Added: " + LibraryUtil.getLocalizeTypeName(e)); //$NON-NLS-1$
		}
	}

	/**
	 * remove element from referenced list
	 * 
	 * @param e MethodElement
	 */
	public void removeReferencedElement(MethodElement e) {
		if (referencedElements.contains(e)) {
			referencedElements.remove(e);
			if (debug) {
				System.out
						.println("--- Reference Element Removed: " + LibraryUtil.getLocalizeTypeName(e)); //$NON-NLS-1$
			}
		}
	}

	/**
	 * get all the referenced elements
	 * 
	 * @return List
	 */
	public List getReferencedElements() {
		return referencedElements;
	}

	/**
	 * aet the discarded element for this publication. If an element is
	 * discarded, it should not be published and link to it should be link to
	 * mising element page
	 * 
	 * @param e
	 *            MethodElement
	 */
	public void setDiscardedElement(MethodElement e) {

		if (e == null) {
			return;
		}

		if (!discardedElements.contains(e)) {
			discardedElements.add(e);
		}

		// if th fdiscarded element is in the reference list, remove it as well
		removeReferencedElement(e);
	}

	/**
	 * check if an elenment is referenced or not.
	 * 
	 * @param e MethodElement
	 * @return boolean
	 */
	public boolean isReferencedElement(MethodElement e) {
		return (e != null) && referencedElements.contains(e);
	}

	/**
	 * get the published elements
	 * 
	 * @return List
	 */
	public List getPublishedElements() {
		return publishedElements;
	}

	/**
	 * set the default target for the referenced elements
	 * 
	 * @param target MethodElement
	 */
	public void setTargetElement(MethodElement target) {
		this.defaultTarget = target;
	}

	/**
	 * check if there is a closure or not
	 * 
	 * @return boolean
	 */
	public boolean hasClosure() {
		return false;
	}

	/**
	 * check if an element is in closure or not.
	 * 
	 * @param e MethodElement
	 * @return boolean
	 */
	public boolean inClosure(MethodElement e) {
		return true;
	}

	/**
	 * add elements to closure
	 * 
	 * @param items List
	 */
	public void addClosureElements(List items) {
		// do nothing
	}

	/**
	 * make a closure
	 *
	 */
	public void makeElementClosure() {
		// do nothing
	}

	public boolean showBrokenLinks() {
		return !options.isConvertBrokenLinks();
	}
	
	/**
	 * get the flag on whether to show extra descriptor info. 
	 * If true, information from linked element will be included in the descriptor page.
	 * 
	 * @return boolean
	 */
	public boolean showExtraInfoForDescriptors() {
		return options.isShowMethodContentInDescriptors();
	}


	/**
	 * show descriptors on method element page
	 */
	public boolean showRelatedDescriptors() {
		return options.showRelatedDescriptors;
	}
	
	/**
	 * get the tab id for the activity layout
	 * 
	 * @return String
	 */
	public String getDefaultActivityTab() {
		return options.getDefaultActivityTab();
	}
}
