/*******************************************************************************
 * Copyright (c) 2004, 2011 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 API and implementation
 *******************************************************************************/
package org.eclipse.wst.html.core.internal.validate;

import java.util.Iterator;

import org.eclipse.wst.html.core.internal.contentmodel.HTMLElementDeclaration;
import org.eclipse.wst.html.core.internal.contentmodel.HTMLPropertyDeclaration;
import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeEntry;
import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeRegistry;
import org.eclipse.wst.html.core.internal.provisional.HTML50Namespace;
import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegion;
import org.eclipse.wst.sse.core.internal.provisional.text.ITextRegionList;
import org.eclipse.wst.sse.core.internal.validate.ErrorInfo;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.document.InvalidCharacterException;
import org.eclipse.wst.xml.core.internal.document.SourceValidator;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMElement;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;

class SyntaxValidator extends PrimeValidator implements ErrorState {


	static private boolean isValidRegion(ITextRegion rgn) {
		String type = rgn.getType();
		if (type == null)
			return false; // no type is invalid.
		if (type == DOMRegionContext.XML_END_TAG_OPEN || type == DOMRegionContext.XML_TAG_NAME || type == DOMRegionContext.XML_TAG_CLOSE) {
			return true;
		}
		return false;
	}

	static private String getTagName(IStructuredDocumentRegion tag) {
		ITextRegionList regions = tag.getRegions();
		Iterator iter = regions.iterator();
		while (iter.hasNext()) {
			ITextRegion rgn = (ITextRegion) iter.next();
			if (rgn.getType() == DOMRegionContext.XML_TAG_NAME)
				return tag.getText(rgn);
		}
		return "";//$NON-NLS-1$
	}

	static private boolean isEmptyContent(CMElementDeclaration decl) {
		return (decl != null) && (decl.getContentType() == CMElementDeclaration.EMPTY);
	}

	public SyntaxValidator() {
		super();
	}

	public boolean isAdapterForType(Object type) {
		return ((type == SyntaxValidator.class) || super.isAdapterForType(type));
	}

	class ElementInfo {
		public ElementInfo() {
			super();
		}

		public IDOMElement target = null;
		public CMElementDeclaration decl = null;
		public IStructuredDocumentRegion startTag = null;
		public IStructuredDocumentRegion endTag = null;
		public boolean hasStartTag() {return startTag != null;}
		public boolean hasEndTag() {return endTag != null;}
		public boolean isXHTML = false;
		public boolean isXHTML5 = false;
	}

	public void validate(IndexedRegion indexedNode) {
		Node node = (Node) indexedNode;
		validateChildren(node);

		if (node.getNodeType() != Node.ELEMENT_NODE)
			return;
		if (!(node instanceof IDOMElement))
			return;

		ElementInfo info = new ElementInfo();
		info.target = (IDOMElement) node;

		// gather information to validate from target at once.
		getInfo(info);

		validateTags(info);
		if (info.target.isGlobalTag()) {
			validateNames(info);
			if (info.decl != null && info.isXHTML) {
				validateTagCase(info);
			}
		}

		//validate the syntax of the attributes
		validateAttributes(info);
	}

	private void getInfo(ElementInfo info) {
		info.decl = CMUtil.getDeclaration(info.target);
		info.startTag = info.target.getStartStructuredDocumentRegion();
		info.endTag = info.target.getEndStructuredDocumentRegion();

		Document doc = info.target.getOwnerDocument();
		if (!(doc instanceof IDOMDocument))
			return;
		String typeid = ((IDOMDocument) doc).getDocumentTypeId();
		if (typeid != null) {
			if (typeid.trim().length()!= 0){
				HTMLDocumentTypeEntry entry = HTMLDocumentTypeRegistry.getInstance().getEntry(typeid);
				info.isXHTML = (entry != null && entry.isXMLType());
			}
			else {
				info.isXHTML = getXMLTarget(doc);
				info.isXHTML5 = info.isXHTML;
			}
		}
	}
	
	private boolean getXMLTarget(Document doc) {
		if (doc == null)
			return false;
		Node child = doc.getFirstChild();
		while (child != null) {
			if (child.getNodeType() == Node.ELEMENT_NODE) {
				if (child.getNodeName().equalsIgnoreCase("html")){
					if (child.getAttributes()!= null){
						NamedNodeMap attrs = child.getAttributes();
						for (int i = 0; i < attrs.getLength(); i++) {
							Attr a = (Attr) attrs.item(i);
							if (a.getName().equalsIgnoreCase(HTML50Namespace.ATTR_NAME_XMLNS))
									return true;
						}
					}
					return false;
				}
				
			}
			child = child.getNextSibling();
		}
		return false;
	}

	class TagErrorInfoImpl extends AbstractErrorInfo {
		private String hint = null;

		public TagErrorInfoImpl(int state, IStructuredDocumentRegion tag, String hint) {
			super(state, new Segment(tag));
			this.hint = hint;
		}

		public String getHint() {
			return hint;
		}

		public short getTargetType() {
			return Node.ELEMENT_NODE;
		}
	}

	private boolean isEndTagCorrupted(ElementInfo info) {
		ITextRegionList regions = info.endTag.getRegions();
		if (regions == null || regions.isEmpty())
			return false;
		Iterator iter = regions.iterator();
		while (iter.hasNext()) {
			ITextRegion rgn = (ITextRegion) iter.next();
			if (!isValidRegion(rgn))
				return true; // found invalid region type.
		}
		return false; // all regions are valid.
	}

	private String getEndTagFullText(ElementInfo info) {
		String hint = "";//$NON-NLS-1$
		ITextRegionList regions = info.endTag.getRegions();
		Iterator iter = regions.iterator();
		while (iter.hasNext()) {
			ITextRegion rgn = (ITextRegion) iter.next();
			String type = rgn.getType();
			if (type == null)
				continue;
			if (type == DOMRegionContext.XML_END_TAG_OPEN || type == DOMRegionContext.XML_TAG_CLOSE)
				continue;
			hint += info.endTag.getFullText(rgn);
		}
		return hint;
	}

	private void reportCorruptedEndTagError(ElementInfo info) {
		String hint = getEndTagFullText(info);
		TagErrorInfoImpl error = new TagErrorInfoImpl(UNDEFINED_NAME_ERROR, info.endTag, hint);
		this.reporter.report(error);
	}

	private void validateTags(ElementInfo info) {
		if (info.hasStartTag()) {
			if (!info.target.isStartTagClosed()) {
				// Mark the whole START tag as an error segment.
				Segment errorSeg = new Segment(info.startTag);
				report(UNCLOSED_TAG_ERROR, errorSeg, info.target);
			}
		}
		else {
			if (info.hasEndTag()) {
				if (info.decl != null) {
					//if xhtml then must have end tag
					//else determine if end tag is omissible
					if (info.isXHTML) {
						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_END_TAG_NAME);
						report(MISSING_START_TAG_ERROR, errorSeg, info.target);
					} else {
						//determine if the end tag is omissible
						boolean canOmitStartTag = false;
						if(info.decl instanceof HTMLPropertyDeclaration) {
							int omitType = ((HTMLPropertyDeclaration)info.decl).getOmitType();
							canOmitStartTag = omitType == HTMLElementDeclaration.OMIT_BOTH;
						}
					
						if (!canOmitStartTag && !info.target.hasChildNodes()) {
							if (info.target.isContainer()) {
								// Set the error mark to the start of the element.
								Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_END_TAG);
								report(MISSING_START_TAG_ERROR, errorSeg, info.target);
							}
							else {
								// Mark the whole END tag as an error segment.
								Segment errorSeg = new Segment(info.endTag);
								report(UNNECESSARY_END_TAG_ERROR, errorSeg, info.target);
							}
						}
					}
				}
			}
		}

		if (info.hasEndTag()) {
			if (!info.target.isClosed()) {
				// Set the whole END tag as error segment.
				Segment errorSeg = new Segment(info.endTag);
				report(UNCLOSED_END_TAG_ERROR, errorSeg, info.target);
			}
		}
		else {
			if (info.isXHTML) { // XHTML
				//if editor closed during validation this could be null
				IStructuredDocumentRegion structRegion = info.target.getStartStructuredDocumentRegion();
				if (!info.target.isEmptyTag() && structRegion != null && DOMRegionContext.XML_TAG_OPEN.equals(structRegion.getFirstRegion().getType())) {
					/*
					 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=248963 :
					 * report empty tags not written as such, but only when
					 * they follow actual XML/HTML syntax
					 */
					if (isEmptyContent(info.decl)) {
						// EMPTY element should be written in <.../> form
						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
						report(INVALID_EMPTY_ELEMENT_TAG, errorSeg, info.target);
					}
					else {
						// end tag is required.
						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
						report(MISSING_END_TAG_ERROR, errorSeg, info.target);
					}
				}
			}
			else { // HTML
				if (info.hasStartTag()) {
					if (info.decl != null && CMUtil.isHTML(info.decl) && !info.target.isEmptyTag() && !CMUtil.isEndTagOmissible(info.decl) && DOMRegionContext.XML_TAG_OPEN.equals(info.startTag.getFirstRegion().getType())) {
						// Set the error mark to the end of the element.
						Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG);
						report(MISSING_END_TAG_ERROR, errorSeg, info.target);
					}
				}
			}
		}
	}

	/* perform validation about tag name definition. */
	private void validateNames(ElementInfo info) {
		boolean corrupted = info.hasEndTag() && isEndTagCorrupted(info);
		if (info.decl == null) {
			// If no declaration is retrieved, the target is really
			// unknown element.
			if (!info.hasStartTag() && corrupted) {
				reportCorruptedEndTagError(info);
			}
			else {
				Segment errorSeg = FMUtil.getSegment(info.target, FMUtil.SEG_START_TAG_NAME);
				report(UNDEFINED_NAME_ERROR, errorSeg, info.target);
			}
		}
		else {
			// Even if a declaration could be retrieved, if the end
			// tag is corrupted, it should be reported as undefined
			// name. (D202493)
			if (corrupted) {
				reportCorruptedEndTagError(info);
			}
		}
	}

	/* perform validation tag case only for XHTML document */
	private void validateTagCase(ElementInfo info) {
		String declared = info.decl.getElementName();
		String startTagName = "";//$NON-NLS-1$
		String endTagName = "";//$NON-NLS-1$
		if (declared == null)
			return;

		if (info.isXHTML5){
			if (info.hasStartTag()) {
				startTagName = getTagName(info.startTag);
				if (info.hasEndTag()) {
					endTagName = getTagName(info.endTag);
					if (!endTagName.equals(startTagName)){
						TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.endTag, endTagName);
						this.reporter.report(error);
					}
				}
			}
			
		}
		else
		{
			// start tag
			if (info.hasStartTag()) {
				startTagName = getTagName(info.startTag);
				if (!declared.equals(startTagName)) {
					TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.startTag, startTagName);
					this.reporter.report(error);
				}
			}
			// end tag
			if (info.hasEndTag()) {
				endTagName = getTagName(info.endTag);
				if (!info.hasStartTag() || (!endTagName.equals(startTagName))) {
					if (!declared.equals(endTagName)) {
						TagErrorInfoImpl error = new TagErrorInfoImpl(MISMATCHED_ERROR, info.endTag, endTagName);
						this.reporter.report(error);
					}
				}
			}
		}
		
	}

	private void validateChildren(Node target) {
		if ((target.getNodeType() == Node.ELEMENT_NODE) && CMUtil.isForeign((Element) target))
			return;

		for (Node child = target.getFirstChild(); child != null; child = child.getNextSibling()) {
			switch (child.getNodeType()) {
				case Node.TEXT_NODE :
					{
						IDOMNode text = (IDOMNode) child;
						int charOffset = validateTextSource(text);
						if (charOffset >= 0) {
							charOffset += text.getStartOffset();
							Segment errorSeg = new Segment(charOffset, 1);
							if (errorSeg != null)
								report(INVALID_CHAR_ERROR, errorSeg, text);
						}
						break;
					}
				case Node.COMMENT_NODE :
				case Node.DOCUMENT_TYPE_NODE :
				case Node.PROCESSING_INSTRUCTION_NODE :
				case Node.CDATA_SECTION_NODE :
					{
						IDOMNode tag = (IDOMNode) child;
						if (!tag.isClosed()) {
							Segment errorSeg = FMUtil.getSegment(tag, FMUtil.SEG_WHOLE_TAG);
							if (errorSeg != null)
								report(UNCLOSED_TAG_ERROR, errorSeg, tag);
						}
						break;
					}
				default :
					break;
			}
		}
	}

	private int validateTextSource(IDOMNode text) {
		try {
			SourceValidator validator = new SourceValidator(text);
			validator.validateSource(text.getSource());
		}
		catch (InvalidCharacterException ex) {
			return ex.getOffset();
		}
		return -1;
	}

	/**
	 * <p>Used to validate the syntax of the arguments in a tag.</p>
	 * 
	 * @param info the <code>ElementInfo</code> about the tag to validate 
	 */
	private void validateAttributes(ElementInfo info) {
		if(info != null && info.hasStartTag()) {
			ITextRegionList list = info.startTag.getRegions();

			//for each region in the tag, these make up the arguments
			for(int i = 0; i < list.size(); ++i) {
				ITextRegion region = list.get(i);
				String type = region.getType();
	
				//if the type is undefined then there is a syntax error
				if(type == DOMRegionContext.UNDEFINED) {
					String invalidText = info.startTag.getFullText(region).trim();
					Segment errorSeg = new Segment(info.startTag.getStartOffset() + region.getStart(), invalidText.length());
					report(INVALID_TEXT_IN_ELEM_ERROR, errorSeg, info.target, new String[]{invalidText}, new String[0]);
				}
			}
		}
	}

	private void report(int state, Segment errorSeg, Node node) {
		ErrorInfo info = new ErrorInfoImpl(state, errorSeg, node);
		reporter.report(info);
	}

	private void report(int state, Segment errorSeg, Node node, String[] preTargetMsgInjections, String[] postTargetMsgInjections) {
		ErrorInfo info = new ErrorInfoImpl(state, errorSeg, node, preTargetMsgInjections, postTargetMsgInjections);
		reporter.report(info);
	}
}
