/*******************************************************************************
 * Copyright (c) 2007 Chase Technology Ltd - http://www.chasetechnology.co.uk
 * 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:
 *     Doug Satchwell (Chase Technology Ltd) - initial API and implementation
 *     David Carver (STAR) - bug 230072 - Project level specific validation
 *******************************************************************************/
package org.eclipse.wst.xsl.core.internal.validation;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.xml.xpath.XPathExpressionException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.wst.sse.core.internal.validate.ValidationMessage;
import org.eclipse.wst.xml.core.internal.validation.core.ValidationReport;
import org.eclipse.wst.xml.xpath.core.util.XSLTXPathHelper;
import org.eclipse.wst.xsl.core.ValidationPreferences;
import org.eclipse.wst.xsl.core.XSLCore;
import org.eclipse.wst.xsl.core.internal.XSLCorePlugin;
import org.eclipse.wst.xsl.core.internal.util.Debug;
import org.eclipse.wst.xsl.core.model.CallTemplate;
import org.eclipse.wst.xsl.core.model.Include;
import org.eclipse.wst.xsl.core.model.Parameter;
import org.eclipse.wst.xsl.core.model.StylesheetModel;
import org.eclipse.wst.xsl.core.model.Template;
import org.eclipse.wst.xsl.core.model.XSLAttribute;
import org.eclipse.wst.xsl.core.model.XSLElement;
import org.eclipse.wst.xsl.core.model.XSLNode;
import org.eclipse.wst.xsl.core.Messages;


/**
 * The XSL validator for workspace XSL files.
 * 
 * @author Doug Satchwell
 */
public class XSLValidator
{
	private static XSLValidator instance;
	private IProject project;

	private XSLValidator()
	{
	}

	/**
	 * Validate the given XSL file. Same as <code>validate(xslFile,report,forceBuild)</code> except a new report is created and returned.
	 * 
	 * @param xslFile the XSL file
	 * @param forceBuild true if build should always be forced
	 * @return the validation report
	 * @throws CoreException if any exception occurs while validating
	 */
	public ValidationReport validate(IFile xslFile, boolean forceBuild) throws CoreException
	{
		XSLValidationReport report = new XSLValidationReport(xslFile.getLocationURI().toString());
		project = xslFile.getProject();
		validate(xslFile, report, forceBuild);
		return report;
	}

	/**
	 * Validate the given XSL file using the specified report.
	 * 
	 * @param xslFile the XSL file
	 * @param report the report to use for reporting validation errors
	 * @param forceBuild true if build should always be forced
	 * @return the validation report
	 * @throws CoreException if any exception occurs while validating
	 */
	public void validate(IFile xslFile, XSLValidationReport report, boolean forceBuild) throws CoreException
	{
		StylesheetModel stylesheet;
		if (forceBuild)
			stylesheet = XSLCore.getInstance().buildStylesheet(xslFile);
		else
			stylesheet = XSLCore.getInstance().getStylesheet(xslFile);
		
		project = xslFile.getProject();

		long start;
		if (Debug.debugXSLModel) {
			start = System.currentTimeMillis();
		}
		if (stylesheet!=null)
		{
			try
			{
				calculateProblems(stylesheet, report);
			}
			catch (MaxErrorsExceededException e)
			{
				// do nothing
			}
		}
		if (Debug.debugXSLModel) {
			long end = System.currentTimeMillis();
			System.out.println("VALIDATE "+xslFile+" in "+(end-start)+"ms");
		}
	}

	private void calculateProblems(StylesheetModel stylesheetComposed, XSLValidationReport report) throws MaxErrorsExceededException
	{
		// circular reference check
		checkCircularRef(stylesheetComposed, report);
		// include checks
		checkIncludes(stylesheetComposed, report);
		// template checks
		checkTemplates(stylesheetComposed, report);
		// call-template checks
		checkCallTemplates(stylesheetComposed, report);
		// call-template checks
		if (getPreference(ValidationPreferences.XPATHS) > IMarker.SEVERITY_INFO)
			checkXPaths(stylesheetComposed.getStylesheet(), report);
		
		// TODO a) check globals and b) apply-templates where mode does not exist
	}
	
	private int getPreference(String key)
	{
		if (project == null) {
			return XSLCorePlugin.getDefault().getPluginPreferences().getInt(key);
		}
		
		IEclipsePreferences prefs = new ProjectScope(project).getNode(XSLCorePlugin.getDefault().getBundle().getSymbolicName());
		boolean useProject = prefs.getBoolean(XSLCorePlugin.USE_PROJECT_SETTINGS, false);
		
		int valPref;
		if (useProject) {
			valPref = prefs.getInt(key, ValidationMessage.WARNING);	
		} else {
			valPref = XSLCorePlugin.getDefault().getPluginPreferences().getInt(key);
		}
		return valPref;
	}

	private void checkXPaths(XSLElement xslEl, XSLValidationReport report) throws MaxErrorsExceededException
	{
		validateXPath(xslEl, report, "select"); //$NON-NLS-1$
		validateXPath(xslEl, report, "test"); //$NON-NLS-1$
		validateXPath(xslEl, report, "match"); //$NON-NLS-1$
		for (XSLElement childEl : xslEl.getChildElements())
		{
			checkXPaths(childEl, report);
		}
	}

	private void validateXPath(XSLElement xslEl, XSLValidationReport report, String attName) throws MaxErrorsExceededException
	{
		XSLAttribute att = xslEl.getAttribute(attName);
		if (att != null && att.getValue() != null)
		{
			try
			{
				XSLTXPathHelper.compile(att.getValue());
			}
			catch (XPathExpressionException e)
			{
				createMarker(report, att, getPreference(ValidationPreferences.XPATHS), Messages.XSLValidator_1);
			}
			catch (NullPointerException e)
			{
				// not sure why NPE is being thrown here
			}
		}
	}

	private void checkCircularRef(StylesheetModel stylesheetComposed, XSLValidationReport report) throws MaxErrorsExceededException
	{
		if (stylesheetComposed.hasCircularReference())
			createMarker(report, stylesheetComposed.getStylesheet(), getPreference(ValidationPreferences.CIRCULAR_REF), Messages.XSLValidator_2);
	}

	private void checkIncludes(StylesheetModel stylesheetComposed, XSLValidationReport report) throws MaxErrorsExceededException
	{		
		// includes
		for (Include include : stylesheetComposed.getStylesheet().getIncludes())
		{
			IFile includedFile = include.getHrefAsFile();
			if (includedFile == null || !includedFile.exists())
			{ // included file does not exist
				XSLAttribute att = include.getAttribute("href");  //$NON-NLS-1$
				if (att != null)
					createMarker(report, att, getPreference(ValidationPreferences.MISSING_INCLUDE), Messages.XSLValidator_4 + include.getHref());
				else
					createMarker(report, include, getPreference(ValidationPreferences.NAME_ATTRIBUTE_EMPTY), Messages.XSLValidator_23 );					
			}
			else if (includedFile.equals(include.getStylesheet().getFile()))
			{ // stylesheet including itself!
				createMarker(report, include.getAttribute("href"), getPreference(ValidationPreferences.CIRCULAR_REF), Messages.XSLValidator_6); //$NON-NLS-1$
			}
		}
		//imports
		for (Include include : stylesheetComposed.getStylesheet().getImports())
		{
			IFile includedFile = include.getHrefAsFile();
			if (includedFile == null || !includedFile.exists())
			{ // included file does not exist
				createMarker(report, include.getAttribute("href"), getPreference(ValidationPreferences.MISSING_INCLUDE), Messages.XSLValidator_8 + include.getHref()); //$NON-NLS-1$
			}
			else if (includedFile.equals(include.getStylesheet().getFile()))
			{ // stylesheet including itself!
				createMarker(report, include.getAttribute("href"), getPreference(ValidationPreferences.CIRCULAR_REF), Messages.XSLValidator_10); //$NON-NLS-1$
			}
		}
	}

	private void checkTemplates(StylesheetModel stylesheetComposed, XSLValidationReport report) throws MaxErrorsExceededException
	{
		for (Template template : stylesheetComposed.getStylesheet().getTemplates())
		{
			// check attributes are correct
			if (template.getName() != null)
			{// named template
//				if (template.getMatch() != null)
//					createMarker(report, template, IMarker.SEVERITY_ERROR, "Template cannot specify both name and match attributes");
//				if (template.getMode() != null)
//					createMarker(report, template, IMarker.SEVERITY_ERROR, "Named templates cannot specify a mode");
				checkParameters(report, template);
			} 

			for (Template checkTemplate : stylesheetComposed.getTemplates())
			{
				if (checkTemplate != template && checkTemplate.equals(template))
				{
					if (template.getStylesheet() == stylesheetComposed.getStylesheet() && checkTemplate.getStylesheet() == stylesheetComposed.getStylesheet())
					{// templates in this stylesheet conflict with each other
						createMarker(report, template, getPreference(ValidationPreferences.TEMPLATE_CONFLICT), Messages.XSLValidator_11);
					}
					else if (template.getStylesheet() == stylesheetComposed.getStylesheet())
					{// template in included stylesheet conflicts with this
						createMarker(report, template, getPreference(ValidationPreferences.TEMPLATE_CONFLICT), Messages.XSLValidator_12);
					}
					else
					{// templates in included stylesheets conflict with each other
						createMarker(report, template.getStylesheet(), getPreference(ValidationPreferences.TEMPLATE_CONFLICT), Messages.XSLValidator_13);
					}
				}
			}
		}
	}

	private void checkParameters(XSLValidationReport report, Template template) throws MaxErrorsExceededException
	{
		List<Parameter> parameters = new ArrayList<Parameter>(template.getParameters());
		// reverse the parameters order for checking - for duplicate parameters
		// the first one is valid
		Collections.reverse(parameters);
		Set<Parameter> duplicateParameters = new HashSet<Parameter>();
		// check parameters
		for (Parameter param : parameters)
		{
			if (param.getName() == null)
			{// name is required
				createMarker(report, param, getPreference(ValidationPreferences.NAME_ATTRIBUTE_MISSING), Messages.XSLValidator_14);
			}
			else if (param.getName().trim().length() == 0)
			{// name value is required
				createMarker(report, param, getPreference(ValidationPreferences.NAME_ATTRIBUTE_EMPTY), Messages.XSLValidator_15);
			}
			else if (duplicateParameters.contains(param))
			{// don't recheck the parameter
				continue;
			}
			else
			{// check a parameter with the same name does not exist
				for (Parameter checkParam : parameters)
				{
					if (param != checkParam)
					{
						if (param.getName().equals(checkParam.getName()))
						{
							duplicateParameters.add(checkParam);
							createMarker(report, param, getPreference(ValidationPreferences.DUPLICATE_PARAMETER), Messages.XSLValidator_16);
						}
					}
				}
			}
		}
	}

	private void checkCallTemplates(StylesheetModel stylesheetComposed, XSLValidationReport report) throws MaxErrorsExceededException
	{
		for (CallTemplate calledTemplate : stylesheetComposed.getStylesheet().getCalledTemplates())
		{
			if (calledTemplate.getName() != null)
			{
				// get the list of templates that might be being called by this
				// template call
				List<Template> templateList = stylesheetComposed.getTemplatesByName(calledTemplate.getName());
				if (templateList.size() == 0)
				{
					Object[] messageArgs = { calledTemplate.getName() };
					createMarker(report, calledTemplate.getAttribute("name"), getPreference(ValidationPreferences.CALL_TEMPLATES), MessageFormat.format(Messages.XSLValidator_18, messageArgs)); //$NON-NLS-1$
				}
				else
				{
					Template namedTemplate = templateList.get(0);
					for (Parameter calledTemplateParam : calledTemplate.getParameters())
					{
						boolean found = false;
						for (Parameter namedTemplateParam : namedTemplate.getParameters())
						{
							if (calledTemplateParam.getName().equals(namedTemplateParam.getName()))
							{
								found = true;
								if (!namedTemplateParam.isValue() && !calledTemplateParam.isValue()) {
								    Object[] messageArgs = { calledTemplateParam.getName() };	
									createMarker(report, calledTemplateParam, getPreference(ValidationPreferences.EMPTY_PARAM), MessageFormat.format(Messages.XSLValidator_20, messageArgs));
								}
								break;
								
							}
						}
						if (!found) {
							Object[] messageArgs = { calledTemplateParam.getName() };
							createMarker(report, calledTemplateParam.getAttribute("name"), getPreference(ValidationPreferences.MISSING_PARAM), MessageFormat.format(Messages.XSLValidator_22, messageArgs)); //$NON-NLS-1$
						}
					}
					if (getPreference(ValidationPreferences.MISSING_PARAM) > IMarker.SEVERITY_INFO)
					{
						for (Parameter namedTemplateParam : namedTemplate.getParameters())
						{
							if (!namedTemplateParam.isValue())
							{
								boolean found = false;
								for (Parameter calledTemplateParam : calledTemplate.getParameters())
								{
									if (calledTemplateParam.getName().equals(namedTemplateParam.getName()))
									{
										found = true;
										break;
									}
								}
								if (!found) {
									Object[] messageArgs = { namedTemplateParam.getName() };
									createMarker(report, calledTemplate, getPreference(ValidationPreferences.MISSING_PARAM), MessageFormat.format(Messages.XSLValidator_3, messageArgs));
								}
							}
						}
					}
				} 
			}
		}
	}

	private void createMarker(XSLValidationReport report, XSLNode xslNode, int severity, String message) throws MaxErrorsExceededException
	{
		if (severity > IMarker.SEVERITY_INFO)
		{
			if (report.getErrors().size() + report.getWarnings().size() > getPreference(ValidationPreferences.MAX_ERRORS))
				throw new MaxErrorsExceededException();
			switch (severity)
			{
				case IMarker.SEVERITY_ERROR:
					report.addError(xslNode, message);
					break;
				case IMarker.SEVERITY_WARNING:
					report.addWarning(xslNode, message);
					break;
			}
		}
	}

	/**
	 * Get the singleton XSLValidator instance.
	 * 
	 * @return the singleton XSLValidator instance
	 */
	public static XSLValidator getInstance()
	{
		if (instance == null)
			instance = new XSLValidator();
		return instance;
	}
}
