/*******************************************************************************
 *  Copyright (c) 2005, 2008 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.ui.internal.cheatsheets.composite.parser;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.help.internal.entityresolver.LocalEntityResolver;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.internal.cheatsheets.Messages;
import org.eclipse.ui.internal.cheatsheets.composite.model.AbstractTask;
import org.eclipse.ui.internal.cheatsheets.composite.model.CompositeCheatSheetModel;
import org.eclipse.ui.internal.cheatsheets.composite.model.EditableTask;
import org.eclipse.ui.internal.cheatsheets.composite.model.TaskGroup;
import org.eclipse.ui.internal.cheatsheets.data.CheatSheetParserException;
import org.eclipse.ui.internal.cheatsheets.data.IParserTags;
import org.eclipse.ui.internal.cheatsheets.data.ParserStatusUtility;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class CompositeCheatSheetParser implements IStatusContainer {
	
	private DocumentBuilder documentBuilder;
	
	private IStatus status;
	
	private int nextTaskId = 0;
	
	
	/**
	 *  Gets the status of the last call to parseGuide
	 */
	
	public IStatus getStatus() {
		return status;
	}
	
	/**
	 * Returns the DocumentBuilder to be used by composite cheat sheets.
	 */
	public DocumentBuilder getDocumentBuilder() {
		if(documentBuilder == null) {
			try {
				documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
				documentBuilder.setEntityResolver(new LocalEntityResolver());
			} catch (Exception e) {
				addStatus(IStatus.ERROR, Messages.ERROR_CREATING_DOCUMENT_BUILDER, e);
			}
		}
		return documentBuilder;
	}
		
	public void addStatus(int severity, String message, Throwable exception) { 
		status = ParserStatusUtility.addStatus(status, severity, message, exception);
	}
	
	/**
	 * Parse a composite cheat sheet from a url. The parser status will be set as a result
	 * of this operation, if the status is IStatus.ERROR the parser returns null  
	 * @param url The url of the input
	 * @return A valid composite cheat sheet or null if there was an error
	 */
	public CompositeCheatSheetModel parseGuide(URL url) {
		status = Status.OK_STATUS;
		if(url == null) {
			String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object[] {""})); //$NON-NLS-1$
			addStatus(IStatus.ERROR,  message,  null);
			return null;
		}

		InputStream is = null;	

		try {
			is = url.openStream();

			if (is == null) {
				String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object[] {url.getFile()}));
				addStatus(IStatus.ERROR,  message,  null);
				return null;
			}
		} catch (Exception e) {
			String message = NLS.bind(Messages.ERROR_OPENING_FILE, (new Object[] {url.getFile()}));
			addStatus(IStatus.ERROR,  message,  e);
			return null;
		}
		
		Document document;	
		String filename = url.getFile();
		try {
			InputSource inputSource = new InputSource(is);
			document = getDocumentBuilder().parse(inputSource);
		} catch (IOException e) {
			String message = NLS.bind(Messages.ERROR_OPENING_FILE_IN_PARSER, (new Object[] {filename}));
			addStatus(IStatus.ERROR,  message,  e);
			return null;
		} catch (SAXParseException spe) {
			String message = NLS.bind(Messages.ERROR_SAX_PARSING_WITH_LOCATION, (new Object[] {filename, new Integer(spe.getLineNumber()), new Integer(spe.getColumnNumber())}));
			addStatus(IStatus.ERROR,  message,  spe);
			return null;
		} catch (SAXException se) {
			String message = NLS.bind(Messages.ERROR_SAX_PARSING, (new Object[] {filename}));
			addStatus(IStatus.ERROR,  message, se);
			return null;
		} finally {
			try {
				is.close();
			} catch (Exception e) {
			}
		}
		
		CompositeCheatSheetModel result = parseCompositeCheatSheet(document, url);
		return result;		
	}

	/**
	 * Parse a composite cheatsheet. The parser status will be set as a result
	 * of this operation, if the status is IStatus.ERROR the parser returns null  
	 * @param url The url of the input. This is only used so the model can record
	 * its input location
	 * @param document the document to be parse
	 * @return A valid composite cheat sheet or null if there was an error
	 * @return
	 */
	public CompositeCheatSheetModel parseCompositeCheatSheet(Document document, URL url)   {
		status = Status.OK_STATUS;
		try {
			// If the document passed is null return a null tree and update the status
			if (document != null) {
				Node rootnode = document.getDocumentElement();
				
				// Is the root node correct?
				if( !rootnode.getNodeName().equals(ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET )) {
					String message = NLS.bind(Messages.ERROR_PARSING_ROOT_NODE_TYPE, (
							new Object[] {ICompositeCheatsheetTags.COMPOSITE_CHEATSHEET}));
					throw new CheatSheetParserException(message);
				}
				
				String name = "";  //$NON-NLS-1$
				boolean nameFound = false;
				String explorerId = ICompositeCheatsheetTags.TREE;
				
				NamedNodeMap attributes = rootnode.getAttributes();
				if (attributes != null) {
					for (int x = 0; x < attributes.getLength(); x++) {
						Node attribute = attributes.item(x);
						String attributeName = attribute.getNodeName();
						if ( attributeName != null && attributeName.equals(ICompositeCheatsheetTags.NAME)) {
							nameFound = true;
							name= attribute.getNodeValue();
						}
						if (attributeName.equals(ICompositeCheatsheetTags.EXPLORER)) {
							explorerId= attribute.getNodeValue();
						}
					}
				}
				CompositeCheatSheetModel compositeCS = new CompositeCheatSheetModel(name, name, explorerId);
				
				parseCompositeCheatSheetChildren(rootnode, compositeCS);
				
				compositeCS.getDependencies().resolveDependencies(this);
				
				if (compositeCS.getRootTask() == null) {
					addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_ROOT, null);
				} 
				if (!nameFound) {
					addStatus(IStatus.ERROR, Messages.ERROR_PARSING_CCS_NO_NAME, null);
				}
				if (status.getSeverity() != IStatus.ERROR) {
					compositeCS.setContentUrl(url);
				    return compositeCS;
				}
			} 
			return null;
		} catch(CheatSheetParserException e) {
			addStatus(IStatus.ERROR, e.getMessage(), null);
			return null;
		}	
	}

	private void parseCompositeCheatSheetChildren(Node compositeCSNode, CompositeCheatSheetModel model) {
		nextTaskId = 0;
		NodeList childNodes = compositeCSNode.getChildNodes();
		for (int index = 0; index < childNodes.getLength(); index++) {
			Node nextNode = childNodes.item(index);
			if (isAbstractTask(nextNode.getNodeName()) ) {
				AbstractTask task = parseAbstractTask(nextNode, model);
			    if (model.getRootTask() == null ) { 
					model.setRootTask(task);
					parseTaskChildren(nextNode, task, model);
			    } else {
				    addStatus(IStatus.ERROR, Messages.ERROR_PARSING_MULTIPLE_ROOT, null);
			    }
			}
		}		
	}

	public static boolean isAbstractTask(String nodeName) {
		return nodeName == ICompositeCheatsheetTags.TASK ||
			nodeName == ICompositeCheatsheetTags.TASK_GROUP;
	}
	
	private void parseTaskChildren(Node parentNode, AbstractTask parentTask, CompositeCheatSheetModel model) {
		NodeList childNodes = parentNode.getChildNodes();
		ITaskParseStrategy strategy = parentTask.getParserStrategy();
		strategy.init();
		for (int index = 0; index < childNodes.getLength(); index++) {
			Node childNode = childNodes.item(index);
			if (childNode.getNodeType() == Node.ELEMENT_NODE) {
				String nodeName = childNode.getNodeName();
				if (nodeName == IParserTags.PARAM) {
					addParameter(parentTask, childNode.getAttributes());			
				} else if (nodeName == IParserTags.INTRO) {
					parentTask.setDescription(MarkupParser.parseAndTrimTextMarkup(childNode));
				} else if (nodeName == ICompositeCheatsheetTags.ON_COMPLETION) {
					parentTask.setCompletionMessage(MarkupParser.parseAndTrimTextMarkup(childNode));						
				} else if (nodeName == ICompositeCheatsheetTags.DEPENDS_ON) {
					parseDependency(childNode, parentTask, model);
				} else if (CompositeCheatSheetParser.isAbstractTask(nodeName)) {
					if (parentTask instanceof TaskGroup) {
					    AbstractTask task = parseAbstractTask(childNode, model);
					    ((TaskGroup)parentTask).addSubtask(task);
					    parseTaskChildren(childNode, task, model);
					}
			    } else {
					if (!strategy.parseElementNode(childNode, parentNode, parentTask, this)) {
						String message = NLS
						.bind(
								Messages.WARNING_PARSING_UNKNOWN_ELEMENT,
								(new Object[] { nodeName,
										parentNode.getNodeName() }));
				        addStatus(IStatus.WARNING, message, null);
					}
				}
			}
		}	
		// Check for missing attributes and add dependencies if this was a sequence
		strategy.parsingComplete(parentTask, this);
	}

	private void parseDependency(Node taskNode, AbstractTask task, CompositeCheatSheetModel model) {
		NamedNodeMap attributes = taskNode.getAttributes();
		if (attributes != null) {
		     Node taskAttribute = attributes.getNamedItem(ICompositeCheatsheetTags.TASK);
		     if (taskAttribute != null) {
		    	 String requiredTaskId = taskAttribute.getNodeValue();
		    	 model.getDependencies().addDependency(task, requiredTaskId);
		     } else {
		    	 addStatus(IStatus.ERROR, Messages.ERROR_PARSING_NO_ID, null);
		     }
		}	
	}

	private void addParameter(AbstractTask parentTask, NamedNodeMap attributes) {
		String name = null;
		String value = null;

		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;
				if (attributeName.equals(ICompositeCheatsheetTags.NAME)) {
					name = attribute.getNodeValue();
				}
				if (attributeName.equals(ICompositeCheatsheetTags.VALUE)) {
					value= attribute.getNodeValue();
				}	
			}
		}
		if (name == null) {
			addStatus(IStatus.WARNING, Messages.ERROR_PARSING_NO_NAME, null);
			return;
		} else if (value == null) {
			addStatus(IStatus.WARNING, Messages.ERROR_PARSING_NO_VALUE, null);
			return;
		} else {
			parentTask.getParameters().put(name, value);
		}
		
	}

	private AbstractTask parseAbstractTask(Node taskNode, CompositeCheatSheetModel model) {
		AbstractTask task;
		NamedNodeMap attributes = taskNode.getAttributes();
		String kind = null;
		String name = null;
		String id = null;
		boolean skippable = false;
		if (attributes != null) {
			for (int x = 0; x < attributes.getLength(); x++) {
				Node attribute = attributes.item(x);
				String attributeName = attribute.getNodeName();
				if (attribute == null || attributeName == null)
					continue;
				if (attributeName.equals(ICompositeCheatsheetTags.KIND)) {
					kind = attribute.getNodeValue();
				}
				if (attributeName.equals(ICompositeCheatsheetTags.NAME)) {
					name= attribute.getNodeValue();
				}
				if (attributeName.equals(IParserTags.ID)) {
					id = attribute.getNodeValue();
				}			
				if (attributeName.equals(IParserTags.SKIP)) {
					skippable = "true".equalsIgnoreCase(attribute.getNodeValue()); //$NON-NLS-1$
				}				
			}
		}

		String nodeName = taskNode.getNodeName();
		if (id == null) {
			id = autoGenerateId();
		}
		if (name == null) {
			String message = NLS.bind(Messages.ERROR_PARSING_TASK_NO_NAME, (new Object[] {nodeName}));
			addStatus(IStatus.ERROR, message, null);
		}
		task = createTask(nodeName, model, kind, id, name);
		task.setSkippable(skippable);

		if (model.getDependencies().getTask(id) != null) {
			String message = NLS.bind(Messages.ERROR_PARSING_DUPLICATE_TASK_ID, (new Object[] {id, }));
			addStatus(IStatus.ERROR, message, null);
		} else {
		    model.getDependencies().saveId(task);
		}

		return task;
	}

	private AbstractTask createTask(String nodeKind, CompositeCheatSheetModel model, String kind, String id, String name) {
		AbstractTask task;
		if (ICompositeCheatsheetTags.TASK_GROUP.equals(nodeKind)) {
			task = new TaskGroup(model, id, name, kind);
		} else {
			task = new EditableTask(model, id, name, kind);
		}
		task.setCompletionMessage(Messages.COMPLETED_TASK);
		return task;
	}
	
	private String autoGenerateId() {
		return "TaskId_" + nextTaskId++; //$NON-NLS-1$
	}

}
