/*******************************************************************************
 * Copyright (c) 2004 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.jst.jsp.ui.tests.modelquery;

import java.io.IOException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import junit.textui.TestRunner;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jst.jsp.ui.internal.JSPUIPlugin;
import org.eclipse.jst.jsp.ui.tests.JSPUITestsPlugin;
import org.eclipse.jst.jsp.ui.tests.Logger;
import org.eclipse.wst.html.core.internal.provisional.HTML40Namespace;
import org.eclipse.wst.html.core.internal.provisional.contenttype.ContentTypeIdForHTML;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryProvider;
import org.eclipse.wst.sse.ui.internal.provisional.registry.AdapterFactoryRegistry;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMContent;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMGroup;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNamedNodeMap;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNodeList;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.CMDocumentManager;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.modelquery.ModelQueryUtil;
import org.eclipse.wst.xml.core.internal.provisional.contenttype.ContentTypeIdForXML;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.w3c.dom.Attr;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * @author pavery
 */
public class ModelQueryTester extends TestCase {

	private final boolean testShippedDTDLookup = false;

	// Our Structured Model, which should always be an XMLModel (or subclass)
	protected IDOMModel fModel = null;

	protected ModelQuery fModelQuery = null;

	public ModelQueryTester(String name) {
		super(name);
	}

	protected static Test suite() {
		return new TestSuite(ModelQueryTester.class);
	}

	public static void main(java.lang.String[] args) {
		if (args == null || args.length == 0) {
			runAll();
		}
		else if (args.length == 1) {
			String methodToRun = args[0].trim();
			runOne(methodToRun);
		}

	}

	protected static void runAll() {
		TestRunner.run(suite());

	}

	protected static void runOne(String methodName) {
		TestSuite testSuite = new TestSuite();
		TestCase test = new ModelQueryTester(methodName);
		testSuite.addTest(test);
		junit.textui.TestRunner.run(testSuite);
	}

	/**
	 * Create an empty HTML model
	 */
	protected void setUpHTML() {
		fModel = (IDOMModel) createModel(ContentTypeIdForHTML.ContentTypeID_HTML);
		initVars();
	}

	/**
	 * Create an empty XML model
	 */
	protected void setUpXML() {
		fModel = (IDOMModel) createModel(ContentTypeIdForXML.ContentTypeID_XML);
		initVars();
	}


	/**
	 * Initialize local fields for this test
	 */
	protected void initVars() {
		fModelQuery = ModelQueryUtil.getModelQuery(fModel.getDocument());


	}

	/**
	 * Test the HTML BODY Element for the "bgcolor" attribute declaration
	 */
	public void testBodyElement() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html><body bgcolor=\"#ffffff\"><form method=\"post\"></form></body></html>"); // set
		// text

		// TEST getting a CMElementDeclaration
		Element bodyElement = (Element) fModel.getIndexedRegion(7); // node at
		// offset7--should
		// be
		// <body>
		CMElementDeclaration bodyDecl = fModelQuery.getCMElementDeclaration(bodyElement);

		int contentType = bodyDecl.getContentType();
		assertTrue("CMElementDeclaration CONTENT TYPE INCORRECT FOR BODY", (contentType == CMElementDeclaration.MIXED));

		// get permissible attrs
		CMNamedNodeMap map = bodyDecl.getAttributes();
		assertTrue("ATTRIBUTES FROM ELEMENT DECLARATION == NULL", (map != null));
		Vector allowed = new Vector();
		for (int i = 0; i < map.getLength(); i++) {
			CMAttributeDeclaration node = (CMAttributeDeclaration) map.item(i);
			String name = node.getNodeName();
			allowed.add(name);
			if (name.equalsIgnoreCase("bgcolor")) {
				assertTrue("GOT INCORRECT ATTRIBUTE NODE TYPE", (node.getNodeType() == CMNode.ATTRIBUTE_DECLARATION));

				CMDataType attrType = node.getAttrType();
				// System.out.println("attribute type > " + attrType);
				assertTrue("COULD NOT GET ATTRIBUTE TYPE", (attrType != null));
				assertTrue("COULDN'T GET IMPLIED VALUE KIND", (attrType.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_NONE));
			}
		}
	}

	/**
	 * Test the HTML HTML Element for its declared children
	 */
	public void testHtmlChildren() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html></html>"); // set text
		Element htmlElement = fModel.getDocument().getDocumentElement();
		CMElementDeclaration htmlDecl = fModelQuery.getCMElementDeclaration(htmlElement);

		// HTML's children are within a group
		CMContent contents = htmlDecl.getContent();

		assertTrue("content type is not a group", contents.getNodeType() == CMNode.GROUP);

		CMGroup group = (CMGroup) contents;
		int operator = group.getOperator();
		CMNodeList childList = group.getChildNodes();
		int max = contents.getMaxOccur();
		int min = contents.getMinOccur();

		// the group should be allowed once, with a sequence whose first entry
		// is the declaration for HEAD
		assertTrue("occurrance of group", min == 1 && max == 1);
		assertTrue("relationship in group", operator == CMGroup.SEQUENCE);
		assertTrue("content descriptor type, position 0", contents.getNodeType() == CMNode.GROUP);
		assertTrue("child order (HEAD first)", childList.item(0).getNodeName().equalsIgnoreCase(HTML40Namespace.ElementName.HEAD));

		assertTrue("content descriptor type, position 1", childList.item(1).getNodeType() == CMNode.GROUP);
		// The second child should be a group as well, containing BODY and
		// FRAMESET with an
		// operator of CMGroup.CHOICE
		assertTrue("content descriptor type, position 1 - relationship of group", ((CMGroup) childList.item(1)).getOperator() == CMGroup.CHOICE);
	}

	public void testFormMethodAttr() {
		setUpHTML();
		fModel.getStructuredDocument().set("<html><body bgcolor=\"#ffffff\"><form method=\"post\"></form></body></html>"); // set
		// text

		// TEST GETTING A CMAttributeDeclaratoin
		Element formElement = (Element) fModel.getIndexedRegion(31); // <form>
		Attr attrNode = formElement.getAttributeNode(HTML40Namespace.ATTR_NAME_METHOD);
		CMAttributeDeclaration methodAttrDecl = fModelQuery.getCMAttributeDeclaration(attrNode);
		assertTrue("Content Model missing the attribute declaration for \"method\"", methodAttrDecl != null);

		List values = getValidStrings(formElement, methodAttrDecl);
		assertTrue("wrong number of values for attribute \"method\"", (values.size() == 2));
		assertTrue("default value for attribute \"method\" is wrong", (methodAttrDecl.getAttrType().getImpliedValue().equalsIgnoreCase("get")));
	}

	/**
	 * A short test to ensure that a DTD can be loaded from a system
	 * reference.
	 * 
	 * Note: May require a functioning network connection for the references
	 * to be resolved properly.
	 * 
	 * @throws IOException
	 */
	public void testDTDLoadFromSystemID_1() throws IOException {
		if (testShippedDTDLookup) {
			setUpXML();
			URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/");
			String diskLocation = null;
			diskLocation = FileLocator.resolve(installationPath).toExternalForm();

			assertTrue("failed to resolve plugin install path", diskLocation != null);
			String content = "<?xml version=\"1.0\"?><!DOCTYPE html SYSTEM " + diskLocation + "TestFiles/DTDs/wapDTDs/WAP-2-0/wml20.dtd\"" + "><html xmlns=\"http://www.w3.org/1999/xhtml\" xmlns:wml=\"http://www.wapforum.org/2001/wml\"></html>";
			fModel.getStructuredDocument().set(content);
			CMDocumentManager documentManagaer = fModelQuery.getCMDocumentManager();
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, false);
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, true);

			Node domNode = (Node) fModel.getIndexedRegion(content.length() - 2);
			CMNode node = fModelQuery.getCMNode(domNode);
			assertTrue("wml20.dtd failed to load", node != null && node.getNodeName().equalsIgnoreCase("html"));
		}
	}


	/**
	 * A short test to ensure that a DTD, the XHTML 1.0 Transitional one, can
	 * be loaded from a system reference.
	 * 
	 * Note: May require a functioning network connection for the references
	 * to be resolved properly.
	 * @throws IOException 
	 */
	public void testDTDLoadFromSystemID_2() throws IOException {
		if (testShippedDTDLookup) {
			URL installationPath = Platform.getBundle(JSPUITestsPlugin.ID).getEntry("/");
			String diskLocation = null;

			diskLocation = FileLocator.resolve(installationPath).toExternalForm();

			assertTrue("failed to resolve plugin install path", diskLocation != null);
			setUpXML();
			String content = "<?xml version=\"1.0\"?><!DOCTYPE html SYSTEM " + diskLocation + "testfiles/XHTML/xhtml1-transitional.dtd\"" + "><html></html>";
			fModel.getStructuredDocument().set(content);

			CMDocumentManager documentManagaer = fModelQuery.getCMDocumentManager();
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD, false);
			documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD, true);

			// see defect 282429
			CMElementDeclaration htmlDecl = (CMElementDeclaration) fModelQuery.getCMNode((Node) fModel.getIndexedRegion(content.length() - 2));
			assertTrue("xhtml1-transitional.dtd not loaded", htmlDecl != null);

			// HTML's children are within a group
			CMContent contents = htmlDecl.getContent();

			assertTrue("content type is not a group", contents.getNodeType() == CMNode.GROUP);

			CMGroup group = (CMGroup) contents;
			int operator = group.getOperator();
			CMNodeList childList = group.getChildNodes();
			int max = contents.getMaxOccur();
			int min = contents.getMinOccur();

			// the group should be allowed once, with a sequence whose first
			// entry
			// is the declaration for HEAD
			assertTrue("occurrance of group", min == 1 && max == 1);
			assertTrue("relationship in group", operator == CMGroup.SEQUENCE);
			assertTrue("content descriptor type, position 0", contents.getNodeType() == CMNode.GROUP);
			assertTrue("child order (HEAD first)", childList.item(0).getNodeName().equals(HTML40Namespace.ElementName.HEAD.toLowerCase()));
			assertTrue("child order (BODY second)", childList.item(1).getNodeName().equals(HTML40Namespace.ElementName.BODY.toLowerCase()));
		}
	}

	/**
	 * A short test to ensure that the DTD for JSP 1.2 tag libraries can be
	 * loaded from a public reference registered in the XML catalog
	 */
	public void testDTDLoadFromPublicID() {
		// No longer provided in WTP
		// TODO: provide DTD?
		// if (testShippedDTDLookup) {
		// setUpXML();
		// String contents = "<!DOCTYPE taglib PUBLIC \"-//Sun Microsystems,
		// Inc.//DTD JSP Tag Library 1.2//EN\">
		// <taglib><tag>foo</tag></taglib>";
		// fModel.getStructuredDocument().set(contents);
		//
		// CMDocumentManager documentManagaer =
		// fModelQuery.getCMDocumentManager();
		// documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_ASYNC_LOAD,
		// false);
		// documentManagaer.setPropertyEnabled(CMDocumentManager.PROPERTY_AUTO_LOAD,
		// true);
		//
		//
		// // taglib
		// CMNode node = fModelQuery.getCMNode((Node)
		// fModel.getIndexedRegion(contents.length() - 2));
		// assertTrue("web-jsptaglibrary_1_2.dtd failed to load through
		// catalog", node != null && node.getNodeType() ==
		// CMNode.ELEMENT_DECLARATION &&
		// node.getNodeName().equalsIgnoreCase("taglib"));
		//
		// // tag
		// node = fModelQuery.getCMNode((Node)
		// fModel.getIndexedRegion(contents.length() - 12));
		// assertTrue("CMElementDeclaration for \"tag\" from
		// web-jsptaglibrary_1_2.dtd is missing", node != null &&
		// node.getNodeType() == CMNode.ELEMENT_DECLARATION &&
		// node.getNodeName().equalsIgnoreCase("tag"));
		// CMContent content = ((CMElementDeclaration) node).getContent();
		// assertTrue("only one occurrence of child group allowed",
		// content.getNodeType() == CMNode.GROUP && content.getMaxOccur() ==
		// 1);
		// }
	}



	public static IStructuredModel createModel(String contentTypeID) {
		// create an empty model with its default factories
		IStructuredModel model = StructuredModelManager.getModelManager().createUnManagedStructuredModelFor(contentTypeID);

		// add editor adapter factories
		AdapterFactoryRegistry adapterRegistry = JSPUIPlugin.getDefault().getAdapterFactoryRegistry();
		Iterator adapterList = adapterRegistry.getAdapterFactories();
		// And all those appropriate for this particular type of content
		while (adapterList.hasNext()) {
			try {
				AdapterFactoryProvider provider = (AdapterFactoryProvider) adapterList.next();
				if (provider.isFor(model.getModelHandler())) {
					provider.addAdapterFactories(model);
				}
			}
			catch (Exception e) {
				Logger.logException(e);
			}
		}
		return model;
	}

	/**
	 * Return the valid values for an attribute with the given declaration on
	 * the given element. Derived from XMLPropertySource
	 */
	private List getValidStrings(Element element, CMAttributeDeclaration attrDecl) {
		CMDataType valuesHelper = attrDecl.getAttrType();
		Vector values = new Vector();

		if (valuesHelper.getImpliedValueKind() == CMDataType.IMPLIED_VALUE_FIXED && valuesHelper.getImpliedValue() != null) {
			// FIXED value
			values.add(valuesHelper.getImpliedValue());
		}
		else {
			// ENUMERATED values
			String[] valueStrings = null;
			// new way
			valueStrings = fModelQuery.getPossibleDataTypeValues(element, attrDecl);
			if (valueStrings == null)
				// older way
				valueStrings = attrDecl.getAttrType().getEnumeratedValues();
			if (valueStrings != null) {
				for (int i = 0; i < valueStrings.length; i++) {
					values.add(valueStrings[i]);
				}
			}
		}
		if (valuesHelper.getImpliedValueKind() != CMDataType.IMPLIED_VALUE_NONE && valuesHelper.getImpliedValue() != null) {
			if (!values.contains(valuesHelper.getImpliedValue()))
				values.add(valuesHelper.getImpliedValue());
		}

		return values;
	}

}