import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Date;
import java.util.Enumeration;

import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Result;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.URIResolver;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotSupportedException;

import javax.xml.transform.OutputKeys;
import org.apache.xml.serializer.*;


/**
 * @version 	1.0
 * @author
 */
public class AttributeDisplayServlet extends HttpServlet {

	private DOMSource mXmlDomSource;
	private Transformer mTransformer;
	private DocumentBuilder mBuilder;
	private TransformerFactory mFactory;
	private String homePath;

	void initBuilder()
		throws ParserConfigurationException, SAXNotSupportedException
	{
		mFactory = TransformerFactory.newInstance();
		// setting URIResolver to point where to search for XSL file used in xsl:include, xsl:import, document().
		mFactory.setURIResolver(new URIResolver(){
			public Source resolve(String href, String base)
				throws TransformerException
				{
					try {
						return loadXML(href);
					} catch (IOException e) {
					} catch (SAXException e) {
					}
					return null;
				}
		});

		if (mFactory.getFeature(DOMSource.FEATURE)
			&& mFactory.getFeature(DOMResult.FEATURE))
		{
			if(mBuilder == null)
			{
				//Instantiate a DocumentBuilderFactory.
				DocumentBuilderFactory mFactory =
					DocumentBuilderFactory.newInstance();

				mFactory.setNamespaceAware(true);

				//Use the DocumentBuilderFactory to create a DocumentBuilder.
				mBuilder = mFactory.newDocumentBuilder();
			}

		}
		else
		{
			throw new org.xml.sax.SAXNotSupportedException(
				"DOM node processing not supported! ");
		}
	}

	/*
	 * Loads XSL file specified
	 *
	 * @param fileName is a name of XSL file to load
	 * @throws IOException, SAXException
	 * */
	public DOMSource loadXML(String fileName) throws IOException, SAXException
	{
		//Use the DocumentBuilder to parse the XSL stylesheet.
		Document tDoc = mBuilder.parse(homePath + fileName);

		// Use the DOM Document to define a DOMSource object.
		DOMSource tDomSource = new DOMSource(tDoc);

		// Set the systemId: note this is actually a URL, not a local filename
		tDomSource.setSystemId(fileName);

		return tDomSource;
	}


public static void dumpXML(org.w3c.dom.Node n)
{
	System.out.println("Node : "+n.getNodeName()+" / "+n.getNodeType()+" / "+n.getNodeValue());
	if(n.hasChildNodes())
	{
		for(n = n.getFirstChild(); n != null; n = n.getNextSibling())
		{
			dumpXML(n);
		}
	}

}
	/*
	 * Initialization method, overriden.
	 *
	 * @param config is a servle config file
	 * @throws ServletException
	 * */
	public void init (ServletConfig config) throws ServletException
	{

		try {


			initBuilder();

			// init home path
			homePath = config.getServletContext().getRealPath("");
			if(!homePath.endsWith(File.separator))
				homePath += File.separator;
			homePath = homePath + "WEB-INF" + File.separator;
			// Process the stylesheet DOMSource and generate a Transformer.
			// If necessary, replace syi_attributes.xsl with your .xsl filename
			mTransformer = mFactory.newTransformer(loadXML("syi_attributes.xsl"));

			// Use the DOM Document to define a DOMSource object.
			// Replace MetaData.xml with your GetAttributesCS or GetProductSellingPages
			// working XML file
			mXmlDomSource = loadXML("MetaData.xml");

			// applying new styles to PI
			// Replace "Attributes_Style.xsl" with your patching XSL stylesheet
			// Process the stylesheet DOMSource and generate a Transformer.
			Transformer mTransformerStyle = mFactory.newTransformer(loadXML("Attributes_Style.xsl"));
			DOMResult modifiedXML = new DOMResult();
			mTransformerStyle.transform(mXmlDomSource, modifiedXML);
			mXmlDomSource = new DOMSource(modifiedXML.getNode());

		} catch (TransformerConfigurationException e) {
			e.printStackTrace();

		} catch (SAXNotSupportedException e) {
			e.printStackTrace();

		} catch (FactoryConfigurationError e) {
			e.printStackTrace();

		} catch (ParserConfigurationException e) {
			e.printStackTrace();

		} catch (TransformerException e) {
			e.printStackTrace();
		} catch (SAXException e) {
			e.printStackTrace();

		} catch (IOException e) {
			e.printStackTrace();
		}

	}
	/**
	* @see javax.servlet.http.HttpServlet#void (javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	*/
	public void doGet(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException {
		ServletOutputStream out = resp.getOutputStream();
		Element ebay = (Element)mXmlDomSource.getNode().getChildNodes().item(0);
		transform(mTransformer, ebay, null, null, new StreamResult(out));

	}

	/**
	* @see javax.servlet.http.HttpServlet#void (javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
	*/
	public void doPost(HttpServletRequest req, HttpServletResponse resp)
		throws ServletException, IOException
	{
		ServletOutputStream out = resp.getOutputStream();
		Element ebay = (Element)mXmlDomSource.getNode().getChildNodes().item(0);
		Document mDoc = ebay.getOwnerDocument();

		// Generating SelectedAttributes section XML
		Element attributes = mDoc.createElement("SelectedAttributes");
		// Create AttributeSet for each vscid selected
		String params[] = req.getParameterValues("vcsid");
		if(params != null)
		{
			for(int i = 0; i < params.length; i++)
			{
				// Reading vscid
				String vcsid = params[i];

				System.out.println("Handling Characters set with id = "+vcsid);
				// Creating Characteristic set
				Element attributeSetElement = mDoc.createElement("AttributeSet");
				attributeSetElement.setAttribute("id", vcsid);
				attributes.appendChild(attributeSetElement);

				// Filling Characteristic set with values
				String attrBaseName = "attr"+vcsid+"_";
				addValues2Attr(req, attributeSetElement, attrBaseName, false);
				attrBaseName = "attr_t"+vcsid+"_";
				addValues2Attr(req, attributeSetElement, attrBaseName, true);
				attrBaseName = "attr_d"+vcsid+"_";
				addValues2Attr(req, attributeSetElement, attrBaseName, true);

				// Check on action, if Action is not present then it's signle refresh page
				if(req.getParameter("Action") != null && req.getParameter("Action").equals("Next"))
				{
					// Here you can put the code that will validate errors.

					// here we simulate AddItem call, you can put you code here to AddItem
					PrintWriter w = new PrintWriter(out);
					w.println("<html><body><h1>Item has been added.</h1></body></html>");
					w.flush();
					return;
				}
			}
		}

		// final transformation for the single refresh page
		transform(mTransformer, ebay, attributes, null, new StreamResult(out));
		System.out.println("got out");
	}

	protected void addValues2Attr(HttpServletRequest req, Element attributeSetElement, String attrBaseName, boolean keepAsNameTag)
	{
		Document mDoc = attributeSetElement.getOwnerDocument();
		Enumeration paramNames = req.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String paramName = (String) paramNames.nextElement();
			if ( paramName.indexOf(attrBaseName) >= 0 ) {
				// Now add the childs.
				String paramId = paramName.substring(attrBaseName.length()); // past attrNNNN
				// We care for one for the prototype
				String params[] = req.getParameterValues(paramName);

				Element attributeElement = mDoc.createElement("Attribute");
				attributeSetElement.appendChild(attributeElement);
				for(int i = 0; i < params.length; i++)
				{
					String paramValue = params[i];
					System.out.println(paramName+" = "+paramValue);
					// Creating Value node
					Element valueElement = mDoc.createElement("Value");
					if(keepAsNameTag)
					{
						// By default all non-date type values should be stored as Name node
						String valTagName = "Name";
						// Date handling
						if(paramName.startsWith("attr_d"))
						{
							if(paramName.endsWith("_d"))
								valTagName = "Day";
							else if(paramName.endsWith("_m"))
								valTagName = "Month";
							else if(paramName.endsWith("_y"))
								valTagName = "Year";

							paramId = paramId.substring(0, paramId.indexOf("_"));

						}

						// Creating and adding value to Value node
						Element nameElement = mDoc.createElement(valTagName);
						Text textEelemnt = mDoc.createTextNode(paramValue);
						nameElement.appendChild(textEelemnt);
						valueElement.appendChild(nameElement);
					}
					else
						valueElement.setAttribute("id", paramValue);
					attributeElement.setAttribute("id",paramId);
					attributeElement.appendChild(valueElement);
				}

			}
		}
	}

	protected synchronized void transform(Transformer transformer, Element ebay, Element attributes, Element errors, Result result)
	{
		if(attributes != null)
			ebay.appendChild(attributes);
		if(errors != null)
			ebay.appendChild(errors);

		try {
			System.out.println("Tranforming........");
			Date start = new java.util.Date();
			transformer.transform(mXmlDomSource, result);
			Date end = new java.util.Date();
			long duration2 = end.getTime() - start.getTime();
			System.out.println("Last Transform took " + duration2 + " ms");
		} catch (TransformerException e) {
			e.printStackTrace();
		}

		if(attributes != null)
			ebay.removeChild(attributes);
		if(errors != null)
			ebay.removeChild(errors);
	}
}
