/*******************************************************************************
 * Copyright (c) 2001, 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
 *     Jens Lukowski/Innoopract - initial renaming/restructuring
 *     
 *******************************************************************************/
package org.eclipse.wst.xml.ui.internal.actions;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.xml.core.internal.contentmodel.CMAttributeDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDataType;
import org.eclipse.wst.xml.core.internal.contentmodel.CMDocument;
import org.eclipse.wst.xml.core.internal.contentmodel.CMElementDeclaration;
import org.eclipse.wst.xml.core.internal.contentmodel.CMNode;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQuery;
import org.eclipse.wst.xml.core.internal.contentmodel.modelquery.ModelQueryAction;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
import org.eclipse.wst.xml.ui.internal.XMLUIMessages;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.ProcessingInstruction;

public abstract class BaseNodeActionManager {


	/**
	 * MyMenuManager
	 */
	public static class MyMenuManager extends MenuManager {
		protected String title;

		public MyMenuManager(String s) {
			super(s);
			title = s;
		}

		public boolean isEnabled() {
			return !isEmpty();
		}

		public String toString() {
			return title;
		}
	}

	public static DocumentType getDoctype(Node node) {
		Document document = (node.getNodeType() == Node.DOCUMENT_NODE) ? (Document) node : node.getOwnerDocument();
		return document.getDoctype();
	}

	protected MenuBuilder menuBuilder = new MenuBuilder();
	protected IStructuredModel fModel;
	protected ModelQuery modelQuery;

	protected BaseNodeActionManager(IStructuredModel model, ModelQuery modelQuery) {
		this.fModel = model;
		this.modelQuery = modelQuery;
	}


	protected void addActionHelper(IMenuManager menu, List modelQueryActionList) {
		List actionList = new Vector();
		for (Iterator i = modelQueryActionList.iterator(); i.hasNext();) {
			ModelQueryAction action = (ModelQueryAction) i.next();
			if (action.getCMNode() != null) {
				int cmNodeType = action.getCMNode().getNodeType();
				if (action.getKind() == ModelQueryAction.INSERT) {
					switch (cmNodeType) {
						case CMNode.ATTRIBUTE_DECLARATION : {
							actionList.add(createAddAttributeAction((Element) action.getParent(), (CMAttributeDeclaration) action.getCMNode()));
							break;
						}
						case CMNode.ELEMENT_DECLARATION : {
							actionList.add(createAddElementAction(action.getParent(), (CMElementDeclaration) action.getCMNode(), action.getStartIndex()));
							break;
						}
					}
				} else if (action.getKind() == ModelQueryAction.REPLACE) {
					if (action.getParent() != null && action.getCMNode() != null) {
						actionList.add(createReplaceAction(action.getParent(), action.getCMNode(), action.getStartIndex(), action.getEndIndex()));
					}
				}
			}
		}
		menuBuilder.populateMenu(menu, actionList, false);
	}

	protected void contributeAction(IMenuManager menu, Action action) {
		if (action != null) {
			menu.add(action);
		}
	}


	public void contributeActions(IMenuManager menu, List selection) {
		int editMode = modelQuery.getEditMode();
		int ic = ModelQuery.INCLUDE_CHILD_NODES;
		int vc = (editMode == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) ? ModelQuery.VALIDITY_STRICT : ModelQuery.VALIDITY_NONE;

		List implicitlySelectedNodeList = null;

		if (selection.size() > 0) {
			implicitlySelectedNodeList = getSelectedNodes(selection, true);

			// contribute delete actions
			contributeDeleteActions(menu, implicitlySelectedNodeList, ic, vc);
		}

		if (selection.size() == 1) {
			Node node = (Node) selection.get(0);

			// contribute edit actions
			contributeEditActions(menu, node);

			// contribute add child actions
			contributeAddChildActions(menu, node, ic, vc);

			// contribute add before actions
			contributeAddSiblingActions(menu, node, ic, vc);
		}

		if (selection.size() > 0) {
			// contribute replace actions
			contributeReplaceActions(menu, implicitlySelectedNodeList, ic, vc);
		}

		if (selection.size() == 0) {
			Document document = ((IDOMModel) fModel).getDocument();
			contributeAddDocumentChildActions(menu, document, ic, vc);
			contributeEditGrammarInformationActions(menu, document);
		}
	}


	protected void contributeAddChildActions(IMenuManager menu, Node node, int ic, int vc) {
		int nodeType = node.getNodeType();

		if (nodeType == Node.ELEMENT_NODE) {
			// 'Add Child...' and 'Add Attribute...' actions
			//
			Element element = (Element) node;

			IMenuManager addAttributeMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_ATTRIBUTE); //$NON-NLS-1$
			IMenuManager addChildMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_CHILD); //$NON-NLS-1$
			menu.add(addAttributeMenu);
			menu.add(addChildMenu);

			CMElementDeclaration ed = modelQuery.getCMElementDeclaration(element);
			if (ed != null) {
				// add insert attribute actions
				//
				List modelQueryActionList = new ArrayList();
				modelQuery.getInsertActions(element, ed, -1, ModelQuery.INCLUDE_ATTRIBUTES, vc, modelQueryActionList);
				addActionHelper(addAttributeMenu, modelQueryActionList);

				// add insert child node actions
				//
				modelQueryActionList = new ArrayList();
				modelQuery.getInsertActions(element, ed, -1, ic, vc, modelQueryActionList);
				addActionHelper(addChildMenu, modelQueryActionList);
			}

			// add PI and COMMENT
			contributePIAndCommentActions(addChildMenu, element, ed, -1);

			// add PCDATA, CDATA_SECTION
			contributeTextNodeActions(addChildMenu, element, ed, -1);

			// add NEW ELEMENT
			contributeUnconstrainedAddElementAction(addChildMenu, element, ed, -1);

			// add ATTRIBUTE
			contributeUnconstrainedAttributeActions(addAttributeMenu, element, ed);
		}
	}


	protected void contributeAddDocumentChildActions(IMenuManager menu, Document document, int ic, int vc) {
		IMenuManager addChildMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_CHILD); //$NON-NLS-1$
		menu.add(addChildMenu);

		// add PI and COMMENT
		contributePIAndCommentActions(addChildMenu, document, -1);

		// add NEW ELEMENT
		contributeUnconstrainedAddElementAction(addChildMenu, document, -1);
	}


	protected void contributeAddSiblingActions(IMenuManager menu, Node node, int ic, int vc) {
		IMenuManager addBeforeMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_BEFORE); //$NON-NLS-1$
		IMenuManager addAfterMenu = new MyMenuManager(XMLUIMessages._UI_MENU_ADD_AFTER); //$NON-NLS-1$
		menu.add(addBeforeMenu);
		menu.add(addAfterMenu);

		Node parentNode = node.getParentNode();
		if (parentNode != null) {
			int index = getIndex(parentNode, node);
			if (parentNode.getNodeType() == Node.ELEMENT_NODE) {
				Element parentElement = (Element) parentNode;
				CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
				if (parentED != null) {
					// 'Add Before...' and 'Add After...' actions
					//
					List modelQueryActionList = new ArrayList();
					modelQuery.getInsertActions(parentElement, parentED, index, ic, vc, modelQueryActionList);
					addActionHelper(addBeforeMenu, modelQueryActionList);

					modelQueryActionList = new ArrayList();
					modelQuery.getInsertActions(parentElement, parentED, index + 1, ic, vc, modelQueryActionList);
					addActionHelper(addAfterMenu, modelQueryActionList);
				}

				// add COMMENT and PI before and after
				contributePIAndCommentActions(addBeforeMenu, parentElement, parentED, index);
				contributePIAndCommentActions(addAfterMenu, parentElement, parentED, index + 1);

				// add PCDATA, CDATA_SECTION before and after
				contributeTextNodeActions(addBeforeMenu, parentElement, parentED, index);
				contributeTextNodeActions(addAfterMenu, parentElement, parentED, index + 1);

				// add NEW ELEMENT before and after
				contributeUnconstrainedAddElementAction(addBeforeMenu, parentElement, parentED, index);
				contributeUnconstrainedAddElementAction(addAfterMenu, parentElement, parentED, index + 1);
			} else if (parentNode.getNodeType() == Node.DOCUMENT_NODE) {
				Document document = (Document) parentNode;
				CMDocument cmDocument = modelQuery.getCorrespondingCMDocument(parentNode);
				if (cmDocument != null) {
					// add possible root element insertions
					//        
					List modelQueryActionList = new ArrayList();
					modelQuery.getInsertActions(document, cmDocument, index, ic, vc, modelQueryActionList);
					addActionHelper(addAfterMenu, modelQueryActionList);

					modelQueryActionList = new ArrayList();
					modelQuery.getInsertActions(document, cmDocument, index + 1, ic, vc, modelQueryActionList);
					addActionHelper(addAfterMenu, modelQueryActionList);
				}

				// add COMMENT and PI before and after
				contributePIAndCommentActions(addBeforeMenu, document, index);
				contributePIAndCommentActions(addAfterMenu, document, index + 1);

				// add ELEMENT before and after
				contributeUnconstrainedAddElementAction(addBeforeMenu, document, index);
				contributeUnconstrainedAddElementAction(addAfterMenu, document, index + 1);
			}
		}
	}

	protected void contributeDeleteActions(IMenuManager menu, List list, int ic, int vc) {
		boolean canRemove = modelQuery.canRemove(list, vc);


		// a delete action with an empty list will produce a disabled menu
		// item
		//
		List resultList = canRemove ? list : Collections.EMPTY_LIST;
		contributeAction(menu, createDeleteAction(resultList));
	}


	protected void contributeEditActions(IMenuManager menu, Node node) {
		contributeEditGrammarInformationActions(menu, node);

		if (node.getNodeType() == Node.PROCESSING_INSTRUCTION_NODE) {
			contributeAction(menu, createEditProcessingInstructionAction((ProcessingInstruction) node));
		} else if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
			contributeAction(menu, createEditAttributeAction((Attr) node, null));
		}
	}


	protected void contributeEditGrammarInformationActions(IMenuManager menu, Node node) {
		Document document = node.getNodeType() == Node.DOCUMENT_NODE ? (Document) node : node.getOwnerDocument();

		DocumentType doctype = getDoctype(node);
		if (doctype == null) {
			contributeAction(menu, createAddDoctypeAction(document, -1));
		}

		if (node.getNodeType() == Node.DOCUMENT_TYPE_NODE) {
			contributeAction(menu, createEditDoctypeAction((DocumentType) node));
		}

		if (doctype == null && getRootElement(document) != null) {
			contributeAction(menu, createEditSchemaInfoAction(getRootElement(document)));
		}
	}

	protected void contributePIAndCommentActions(IMenuManager menu, Document document, int index) {
		// test to make sure that the index isn't before the XML declaration
		// 
		contributeAction(menu, createAddCommentAction(document, index));
		contributeAction(menu, createAddProcessingInstructionAction(document, index));
	}


	protected void contributePIAndCommentActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
		if (parentEd == null || isCommentAllowed(parentEd)) {
			contributeAction(menu, createAddCommentAction(parentElement, index));
			contributeAction(menu, createAddProcessingInstructionAction(parentElement, index));
		}
	}


	protected void contributeReplaceActions(IMenuManager menu, List selectedNodeList, int ic, int vc) {
		// 'Replace With...' actions
		//                                                                                                                   
		IMenuManager replaceWithMenu = new MyMenuManager(XMLUIMessages._UI_MENU_REPLACE_WITH); //$NON-NLS-1$
		menu.add(replaceWithMenu);

		if (modelQuery.getEditMode() == ModelQuery.EDIT_MODE_CONSTRAINED_STRICT && selectedNodeList.size() > 0) {
			Node node = (Node) selectedNodeList.get(0);
			Node parentNode = node.getParentNode();
			if (parentNode != null && parentNode.getNodeType() == Node.ELEMENT_NODE) {
				Element parentElement = (Element) parentNode;
				CMElementDeclaration parentED = modelQuery.getCMElementDeclaration(parentElement);
				if (parentED != null) {
					List replaceActionList = new Vector();
					modelQuery.getReplaceActions(parentElement, parentED, selectedNodeList, ic, vc, replaceActionList);
					addActionHelper(replaceWithMenu, replaceActionList);
				}
			}
		}
	}

	protected void contributeTextNodeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
		if (parentEd == null || isTextAllowed(parentEd)) {
			CMDataType dataType = parentEd != null ? parentEd.getDataType() : null;
			contributeAction(menu, createAddPCDataAction(parentElement, dataType, index));
			contributeAction(menu, createAddCDataSectionAction(parentElement, index));
		}
	}


	protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Document document, int index) {
		if (isUnconstrainedActionAllowed()) {
			if (getRootElement(document) == null) {
				int xmlDeclarationIndex = -1;
				int doctypeIndex = -1;
				NodeList nodeList = document.getChildNodes();
				int nodeListLength = nodeList.getLength();
				for (int i = 0; i < nodeListLength; i++) {
					Node node = nodeList.item(i);
					int nodeType = node.getNodeType();
					if (nodeType == Node.DOCUMENT_TYPE_NODE) {
						doctypeIndex = i;
						break;
					} else if (nodeType == Node.PROCESSING_INSTRUCTION_NODE) {
						ProcessingInstruction pi = (ProcessingInstruction) node;
						if (pi.getTarget().equalsIgnoreCase("xml") && xmlDeclarationIndex == -1) { //$NON-NLS-1$
							xmlDeclarationIndex = i;
						}
					}
				}

				if ((xmlDeclarationIndex == -1 || index > xmlDeclarationIndex) && (doctypeIndex == -1 || index > doctypeIndex)) {
					contributeAction(menu, createAddElementAction(document, null, index));
				}
			}
		}
	}


	protected void contributeUnconstrainedAddElementAction(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd, int index) {
		if (isUnconstrainedActionAllowed()) {
			if (parentEd == null || parentEd.getProperty("isInferred") == Boolean.TRUE || (modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT && isElementAllowed(parentEd))) { //$NON-NLS-1$
				contributeAction(menu, createAddElementAction(parentElement, null, index));
			}
		}
	}


	protected void contributeUnconstrainedAttributeActions(IMenuManager menu, Element parentElement, CMElementDeclaration parentEd) {
		if (isUnconstrainedActionAllowed()) {
			if (parentEd == null || parentEd.getProperty("isInferred") == Boolean.TRUE || modelQuery.getEditMode() != ModelQuery.EDIT_MODE_CONSTRAINED_STRICT) { //$NON-NLS-1$
				contributeAction(menu, createAddAttributeAction(parentElement, null));
			}
		}
	}

	abstract protected Action createAddAttributeAction(Element parent, CMAttributeDeclaration ad);

	abstract protected Action createAddCDataSectionAction(Node parent, int index);

	abstract protected Action createAddCommentAction(Node parent, int index);

	abstract protected Action createAddDoctypeAction(Document parent, int index);

	abstract protected Action createAddElementAction(Node parent, CMElementDeclaration ed, int index);

	abstract protected Action createAddPCDataAction(Node parent, CMDataType dataType, int index);

	abstract protected Action createAddProcessingInstructionAction(Node parent, int index);

	abstract protected Action createAddSchemaInfoAction(Element element);

	abstract protected Action createDeleteAction(List selection);

	abstract protected Action createEditAttributeAction(Attr attribute, CMAttributeDeclaration ad);

	abstract protected Action createEditDoctypeAction(DocumentType doctype);

	abstract protected Action createEditProcessingInstructionAction(ProcessingInstruction pi);

	abstract protected Action createEditSchemaInfoAction(Element element);

	abstract protected Action createRenameAction(Node node);

	abstract protected Action createReplaceAction(Node parent, CMNode cmnode, int startIndex, int endIndex);


	public int getIndex(Node parentNode, Node child) {
		NodeList nodeList = parentNode.getChildNodes();
		int index = -1;
		int size = nodeList.getLength();
		for (int i = 0; i < size; i++) {
			if (nodeList.item(i) == child) {
				index = i;
				break;
			}
		}
		return index;
	}


	public Node getRefChildNodeAtIndex(Node parent, int index) {
		NodeList nodeList = parent.getChildNodes();
		Node refChild = (index >= 0 && index < nodeList.getLength()) ? nodeList.item(index) : null;
		return refChild;
	}


	protected Element getRootElement(Document document) {
		Element result = null;
		NodeList nodeList = document.getChildNodes();
		int nodeListLength = nodeList.getLength();
		for (int i = 0; i < nodeListLength; i++) {
			Node node = nodeList.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				result = (Element) node;
				break;
			}
		}
		return result;
	}


	protected List getSelectedNodes(List list, boolean includeTextNodes) {
		List result = new ArrayList(0);
		for (Iterator i = list.iterator(); i.hasNext();) {
			Object object = i.next();
			if (object instanceof Node) {
				Node node = (Node) object;
				if (node.getNodeType() == Node.TEXT_NODE) {
					if (includeTextNodes) {
						result.add(object);
					}
				} else {
					result.add(node);
				}
			}
		}
		return result;
	}


	protected boolean isCommentAllowed(CMElementDeclaration parentEd) {
		int contentType = parentEd.getContentType();
		return contentType == CMElementDeclaration.ELEMENT || contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.PCDATA || contentType == CMElementDeclaration.ANY;
	}


	protected boolean isElementAllowed(CMElementDeclaration parentEd) {
		int contentType = parentEd.getContentType();
		return contentType == CMElementDeclaration.ELEMENT || contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.ANY;
	}


	protected boolean isTextAllowed(CMElementDeclaration parentEd) {
		int contentType = parentEd.getContentType();
		return contentType == CMElementDeclaration.MIXED || contentType == CMElementDeclaration.PCDATA || contentType == CMElementDeclaration.ANY;
	}


	protected boolean isUnconstrainedActionAllowed() {
		return true;
	}


	protected boolean isWhitespaceTextNode(Node node) {
		return (node != null) && (node.getNodeType() == Node.TEXT_NODE) && (node.getNodeValue().trim().length() == 0);
	}
}
