/**********************************************************************
 * Copyright (c) 2008 IBM Corporation.
 * 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 - Initial API and implementation
 *
 * $Id: XMLTreeOutputter.java,v 1.8 2008/06/27 15:01:42 sleeloy Exp $
 **********************************************************************/

package org.eclipse.cosmos.internal.dr.drs.service.outputter;

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;

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

import org.eclipse.cosmos.dc.provisional.cmdbf.exception.CMDBfException;
import org.eclipse.cosmos.internal.dr.drs.service.handler.common.ILogger;
import org.eclipse.cosmos.internal.dr.drs.service.handler.common.LoggerWrapper;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.AbstractOutputter;
import org.eclipse.cosmos.provisional.dr.drs.service.handler.common.IParameters;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
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;


public class XMLTreeOutputter extends AbstractOutputter {
	public static final String XMLXTREAM="org.eclipse.cosmos.dr.drs.service.handler.xml.XMLStream";; //$NON-NLS-1$
	
	protected String rootId;
	private static ILogger logger = LoggerWrapper.getLogger(XMLTreeOutputter.class);

	/* (non-Javadoc)
	 * @see org.eclipse.cosmos.dr.drs.service.handler.sml.IOutputter#render(java.io.PrintWriter, java.util.Map)
	 */
	public void render(PrintWriter output, IParameters input) throws Exception {
		XMLRepository repository = (XMLRepository)context.getStore().getAttribute(XMLRepository.XMLREPOSITORY);
		if (repository == null)
			throw new CMDBfException(Messages.getString("XMLTreeOutputter.XML_RENDER_ERR")); //$NON-NLS-1$
		

		InputStream istream = repository.getXMLStream(input.getParameter("id")); //$NON-NLS-1$
		
		if (istream != null){
			//make connection to repository
			InputSource is = new InputSource(istream);
			render(output, is);
		}
		
	}

	protected Object getId(Object value){
		return idResolver.getId(value);
	}
	
	protected void render(PrintWriter pw, InputSource input) {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder builder = factory.newDocumentBuilder();
			// Read the entire document into memory
			Document d = builder.parse(input);

			StringBuffer buffer = new StringBuffer("{ identifier: \"object\",  label: \"title\",  items:["); //$NON-NLS-1$
			buffer.append(renderElement(d.getDocumentElement(), true,getId(d.getDocumentElement())));
			buffer.append("]}"); //$NON-NLS-1$
			pw.println(buffer.toString());
			
		} catch (ParserConfigurationException e) {
			logger.error(e);
		} catch (SAXException e) {
			logger.error(e);
		} catch (IOException e) {
			logger.error(e);
		}

	}

	protected StringBuffer renderElement(Element elem, boolean rootElement, Object id) {
		NodeList children = elem.getChildNodes();
		StringBuffer buffer = new StringBuffer();
		StringBuffer childBuffer = new StringBuffer();
		String childrenStr = ""; //$NON-NLS-1$
		StringBuffer textContent = null;
		int count = 0;
		for (int x = 0; x < children.getLength(); x++) {
			Node node = children.item(x);
			if (node.getNodeType() == Element.ELEMENT_NODE) {				
				Object nodeId = getId(node);
				childBuffer.append(renderElement((Element) node, false, nodeId));
				if (childrenStr == "") //$NON-NLS-1$
					childrenStr += "["; //$NON-NLS-1$
				if (count > 0) {
					childrenStr += ","; //$NON-NLS-1$
				}
				childrenStr += "{_reference:\"" + nodeId + "\"}"; //$NON-NLS-1$ //$NON-NLS-2$
				count++;
			}
			if (node.getNodeType() == Element.TEXT_NODE){
				
				String nodeValue = node.getNodeValue();
				//TODO: need to encode text to JSON.  []()
/*				if (nodeValue.trim().length() > 0){
					if (textContent == null) textContent = new StringBuffer();
					textContent.append(nodeValue);
				}
				*/
			}
		}
		if (!rootElement){
			buffer.append(",{title:\"" + elem.getNodeName() + "\",nodeClass:\"element\",object:\"" + id + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		else{
			buffer.append("{title:\"" + elem.getNodeName() + "\",nodeClass:\"rootElement\",object:\"" + id + "\""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		buffer.append(", store:["); //$NON-NLS-1$
		buffer.append("['nodeName', '").append(elem.getNodeName()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		buffer.append(",['prefix', '").append(elem.getPrefix()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		buffer.append(",['namespaceURI', '").append(elem.getNamespaceURI()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		buffer.append(",['baseURI', '").append(elem.getBaseURI()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		buffer.append(",['localName', '").append(elem.getLocalName()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		NamedNodeMap attributes = elem.getAttributes();
		if (attributes.getLength() > 0){
			buffer.append(",");			 //$NON-NLS-1$
			//add properties to the element
			for (int x = 0; x < attributes.getLength(); x++){
				Node attribute = attributes.item(x);
				if (x > 0)
					buffer.append(","); //$NON-NLS-1$
				buffer.append("['"+attribute.getNodeName()+"','").append(attribute.getNodeValue()).append("']"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
		}
		if (textContent != null){
			buffer.append(","); //$NON-NLS-1$
			buffer.append("['text content', '").append(textContent).append("']"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		buffer.append("]"); //$NON-NLS-1$
		if (childrenStr != "") { //$NON-NLS-1$
			childrenStr += "]"; //$NON-NLS-1$
			buffer.append(", children:").append(childrenStr); //$NON-NLS-1$
			buffer.append("}"); //$NON-NLS-1$
			buffer.append(childBuffer);
		} else
			buffer.append("}"); //$NON-NLS-1$
		return buffer;
	}
	
	public static final void main(String argv[]) throws Exception{
//		String filename = "c:\\machine5Win.xml";
//		XMLTreeOutputter out = new XMLTreeOutputter();
//		out.setIdResolver(new SessionResolveFixedTreeIDs());
//		Map input = new HashMap();
//		input.put(XMLTreeOutputter.XMLXTREAM, new FileInputStream(new File(filename)));
//		PrintWriter ps = new PrintWriter(System.out);
//		out.render(ps, input);
//		ps.flush();
		
	}

}
