package dca;

//import stuff
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
import java.net.*;
import javax.xml.parsers.*;
import org.w3c.dom.*;
import org.apache.xml.serialize.*;
import java.util.regex.*;
import java.lang.*;

public class Functions extends HttpServlet {
	
//public static final String serverHost = "goofey.it.uts.edu.au";
public static final String serverHost = "localhost";
public static final int serverPort = 31470;

private boolean formpassvalue = true;	
private String serverresponse = "";
private String setresp = "";
	
		//clears session "removes" cds
		public void clearcart(HttpServletRequest request) throws IOException, ServletException {
			HttpSession session = request.getSession(true);
			
			session.invalidate();
		}
		
		//get the session started here
		public void setSession(HttpServletRequest request, HttpServletResponse response) throws IOException,  ServletException {
		
			HttpSession session = request.getSession(true);
		}
		
		//returns a boolean. Allows the user to see errors in forms etc
		public boolean getFormPass() {
			return formpassvalue;
		
		}
		public void setFormPass(boolean value) {
			formpassvalue = value;
		}
		
		//determines at what stage the user is in the order process
		public int getPass(HttpServletRequest request) throws IOException, ServletException {
			
			HttpSession session = request.getSession(true);

			int getPassvalue;
			
				try {
					getPassvalue = Integer.valueOf(session.getAttribute("step").toString()).intValue();
				}
				catch(Exception e1) {
					getPassvalue = 0;
				}
				
			return getPassvalue;
		}
	
		//Repopulates form data if needed
		public String getValue(HttpServletRequest request, String Value) {
		
			String answer;
			try { 
				if (request.getParameter(Value).equals("null")) {
					answer = "";
				} 
				else { 
					answer = (request.getParameter(Value));
				}  
			} 
			catch (Exception e){
				answer = "";
			} 
			return answer;
		}
		
		//take the users input (cds) and add it to a session
		public void setCD(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
			
			int numberofcds = 0;
 
			PrintWriter out = response.getWriter();
			String productCode;
			String description;
			String unitCost;
			String quanity1;
			int quanity;
			
			HttpSession session = request.getSession(true);
			
			//try to get the current number of cds order from the session
			try {
				numberofcds = Integer.valueOf(session.getAttribute("numberofcds").toString()).intValue();
        	}
			//if that fails the order process hasn't started. Lets setup some CDs
        	catch(Exception e) {
        		session.setAttribute("numberofcds", "0");
        	}
			
			try {
				productCode = request.getParameter("productCode");
				description = request.getParameter("description");
				unitCost = request.getParameter("unitCost");
				quanity1 = request.getParameter("quanity");
				quanity = Integer.valueOf(request.getParameter("quanity").toString()).intValue();
			}
			catch(Exception e1) {
				productCode = "";
				description = "";
				unitCost = "";
				quanity = 0;
				quanity1 = "";
			}
			
			numberofcds++;
			
			//makes sure the user as inserted the correct unitCost data in the right format
			Pattern p = Pattern.compile("\\d{1,5}.\\d{2}");
 			Matcher m = p.matcher(unitCost);
 			boolean b = m.matches();
			boolean pass = true;
			
			if(b && pass) {
			
				//test to make sure cd cost is not over 99999.00
				double testunitcost = Double.valueOf(unitCost).doubleValue();
	
				if(testunitcost < 99999.01) {
				}
				else {
					pass = false;
				}
			
			} 
			else {
				pass = false;
			}
			
			Pattern p1 = Pattern.compile("\\d{1,4}");
 			Matcher m1 = p1.matcher(quanity1);
 			boolean b1 = m1.matches();
			
			if(b1 && pass) {
					
				//quanity = Integer.valueOf(request.getParameter("quanity").toString()).intValue();
				
				if(quanity > 0 && quanity < 1001 && pass) {
				}
				else {
					//session.setAttribute("quanity" + numberofcds, "1");
					pass = false;
					//quanity
				}
			}
				

			if (productCode.equals("")) {
				pass = false;
			}

			if (description.equals("")) {
				pass = false;
			}
			
			//if the entered data is ok add it to the session
			if (pass)
			{
					session.setAttribute("unitCost" + numberofcds, unitCost);
					session.setAttribute("quanity" + numberofcds, "" + quanity);
					session.setAttribute("productCode" + numberofcds, productCode);
					session.setAttribute("description" + numberofcds, description);
					session.setAttribute("numberofcds", "" + numberofcds);
					session.setAttribute("step", "1");

					setFormPass(true);
			
			}
			else {
				setFormPass(false);
			}
			
		}

		//sets the users billing details		
		public void setDetails(HttpServletRequest request) throws IOException, ServletException {
			HttpSession session = request.getSession(true);	

			String ordercompanyvalue = "";
			String shiptocompanyvalue = "";
			String shiptostreet2value = "";
			String orderstreet2value =  "";	
			String currencyvalue ="";
			String tick1 = "";
			String orderstatevalue = "";
			String shiptostatevalue = "";
			String ordernamevalue = "";
			String orderstreet1value = "";
			String ordersuburbvalue = "";
			String orderpostcodevalue = "";
			String ordercountryvalue = "";
			String shiptonamevalue = "";
			String shiptostreet1value = "";
			String shiptosuburbvalue = "";
			String shiptopostcodevalue = "";
			String shiptocountryvalue = "";
			
			boolean pass = true;

			try {
				if (request.getParameter("tick1") != null) {
					tick1 = request.getParameter("tick1");
				}
			}
			catch(Exception e) {
			}
			finally {
			}
						
			try {
			
				ordernamevalue = request.getParameter("name");
				ordercompanyvalue = request.getParameter("company");
				orderstreet1value = request.getParameter("street");
				orderstreet2value = request.getParameter("street2");
				ordersuburbvalue = request.getParameter("suburb");
				orderstatevalue = request.getParameter("state");
				orderpostcodevalue = request.getParameter("postcode");
				ordercountryvalue =  request.getParameter("country");
				currencyvalue = request.getParameter("currencyvalue");
				shiptonamevalue = request.getParameter("name2");
				shiptocompanyvalue = request.getParameter("company2");
				shiptostreet1value = request.getParameter("street12");
				shiptostreet2value = request.getParameter("street22");
				shiptosuburbvalue = request.getParameter("suburb2");
				shiptostatevalue = request.getParameter("state2");
				shiptopostcodevalue = request.getParameter("postcode2");
				shiptocountryvalue = request.getParameter("country2");
				
			}
			catch(Exception e1) {
				
			}
			
			if (tick1.equals("1")) {
				
				shiptonamevalue = ordernamevalue;
				shiptocompanyvalue = ordercompanyvalue;
				shiptostreet1value = orderstreet1value;
				shiptostreet2value = orderstreet2value;
				shiptosuburbvalue = ordersuburbvalue;
				shiptostatevalue = orderstatevalue;
				shiptopostcodevalue = orderpostcodevalue;
				shiptocountryvalue = ordercountryvalue;
			}
			else {

			}
			
			//really too long, I could do better error checking, but I've spend enough time on this code :)
			if (currencyvalue.equals("") | orderstatevalue.equals("") | shiptostatevalue.equals("") 
			| ordernamevalue.equals("")| orderstreet1value.equals("")| ordersuburbvalue.equals("")
			| orderpostcodevalue.equals("")| orderpostcodevalue.equals("")| shiptonamevalue.equals("")
			| shiptostreet1value.equals("")| shiptosuburbvalue.equals("")| shiptopostcodevalue.equals("")
			| shiptocountryvalue.equals("")| ordercountryvalue.equals("") 
			) 
			{
				pass = false;
				setFormPass(false);
	
			}
			if (currencyvalue.equals("AUD") | currencyvalue.equals("USD") | currencyvalue.equals("EUR") | currencyvalue.equals("JPY")) {
			}
			else {
			pass = false;
				setFormPass(false);
			}

			if (pass) {
			//	setFormPass(true);
				session.setAttribute("step", "2");
				
				session.setAttribute("ordercompanyvalue",ordercompanyvalue);
				session.setAttribute("shiptocompanyvalue", shiptocompanyvalue);
				session.setAttribute("shiptostreet2value", shiptostreet2value);
				session.setAttribute("orderstreet2value", orderstreet2value);
				session.setAttribute("currencyvalue", currencyvalue);
				session.setAttribute("orderstatevalue", orderstatevalue);
				session.setAttribute("shiptostatevalue", shiptostatevalue);
				session.setAttribute("ordernamevalue", ordernamevalue);
				session.setAttribute("orderstreet1value", orderstreet1value);
				session.setAttribute("ordersuburbvalue", ordersuburbvalue);
				session.setAttribute("orderpostcodevalue", orderpostcodevalue);
				session.setAttribute("orderpostcodevalue",orderpostcodevalue);
				session.setAttribute("shiptonamevalue",shiptonamevalue);
				session.setAttribute("shiptostreet1value",shiptostreet1value);
				session.setAttribute("shiptosuburbvalue",shiptosuburbvalue);
				session.setAttribute("shiptopostcodevalue",shiptopostcodevalue);
				session.setAttribute("shiptocountryvalue",shiptocountryvalue);
				session.setAttribute("ordercountryvalue",ordercountryvalue);
			
			}
			else {
			//	setFormPass(false);
			}

		}
		
		//gets the number of CDs order
		public int getCD(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
			PrintWriter out = response.getWriter();
			HttpSession session = request.getSession(true);	
			
			int numberofcds = 0;
			
						
			try {
				numberofcds = Integer.valueOf(session.getAttribute("numberofcds").toString()).intValue();
        	}
			//if that fails the order process hasn't started. Lets setup some CDs
        	catch(Exception nocds) {
        		
        	}
			
			return numberofcds;
		}
		
		//processes the request (converts to XML and sends to the server). I really should have made this more than
		//one method. Oh well :)
		public void processRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException, UnknownHostException {
		
			PrintWriter out = response.getWriter();
        	HttpSession session = request.getSession(true);

			int sessionnumber = Integer.valueOf(session.getAttribute("numberofcds").toString()).intValue();
			
			//create an array the size of how many cds are being ordered
			String[][] array1 = new String[sessionnumber][4];
			
			//put cds into an array (would have been nice to have had an array from the start)
			for (int numberofcds = 1; numberofcds < sessionnumber + 1; numberofcds++) {
				
				array1[numberofcds -1][0] = session.getAttribute("productCode" + numberofcds).toString();
				array1[numberofcds -1][1] = session.getAttribute("description" + numberofcds).toString();
				array1[numberofcds -1][2] = session.getAttribute("unitCost" + numberofcds).toString();
				array1[numberofcds -1][3] = session.getAttribute("quanity" + numberofcds).toString();
				
			}
			
			//Get other values here
			String ordercompanyvalue  = session.getAttribute("ordercompanyvalue").toString();
			String shiptocompanyvalue  = session.getAttribute("shiptocompanyvalue").toString();
			String shiptostreet2value  = session.getAttribute("shiptostreet2value").toString();
			String orderstreet2value  = session.getAttribute("orderstreet2value").toString();
			String currencyvalue = session.getAttribute("currencyvalue").toString();
			String orderstatevalue  = session.getAttribute("orderstatevalue").toString();
			String shiptostatevalue  = session.getAttribute("shiptostatevalue").toString();
			String ordernamevalue  = session.getAttribute("ordernamevalue").toString();
			String orderstreet1value  = session.getAttribute("orderstreet1value").toString();
			String ordercountryvalue = session.getAttribute("ordercountryvalue").toString();
			String orderpostcodevalue = session.getAttribute("orderpostcodevalue").toString();
			String shiptonamevalue = session.getAttribute("shiptonamevalue").toString();
			String shiptostreet1value = session.getAttribute("shiptostreet1value").toString();
			String shiptosuburbvalue  = session.getAttribute("shiptosuburbvalue").toString();
			String ordersuburbvalue = session.getAttribute("ordersuburbvalue").toString();
			String shiptopostcodevalue = session.getAttribute("shiptopostcodevalue").toString();
			String shiptocountryvalue  = session.getAttribute("shiptocountryvalue").toString();

			/*
			RANDOM CODE TAKEN FROM:
			http://www.javaranch.com/maha/Resources/gotchas_1_.html#RANDOM
			To get exactly the same results each run
			seed the generator with a repeatable value.
			Create the Random object only once.
			*/
			
			Random wheel = new Random(149L);
			int randInt = 0;
			for (int ia=0; ia<100; ia++) {
      		// generate another random integer, mask off sign bit, take modulus
				randInt = (wheel.nextInt() & Integer.MAX_VALUE) % (999999-1+1) + 1;      		
      		} 
						
			String ordernumbervalue = "" + randInt;
			    
			Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("EST"));
			int year1 = cal.get(Calendar.YEAR);             
    		//java month jan starts at ZERO (WTF?). Add 1.
			int month1 = 1 + cal.get(Calendar.MONTH);          
    		int day1 = cal.get(Calendar.DAY_OF_MONTH);     
			
			String yearvalue = "" + year1;
			String monthvalue = "" + month1;
			String dayvalue = "" + day1;
			
			
			/*
			Socket and some XML stuff taken from LAB06 and LAB08
			*/
			Socket mySocket = null;          // socket object
        	PrintWriter sockOut = null;      // to send data to the socket
        	BufferedReader sockIn = null;    // to receive data from the socket
			
			try {

				mySocket = new Socket(serverHost, serverPort);
				sockOut = new PrintWriter(mySocket.getOutputStream(), true);
       	 		sockIn = new BufferedReader(new InputStreamReader(mySocket.getInputStream()));
				

       		}
			/*
			Add some code to fall over nicely?
			*/
			catch (UnknownHostException e) {
            	throw e; 
        	} 
			catch (IOException e) {
            	throw e; 
        	}
			sockOut.println("<?xml version=\"1.0\"?>");
			
			/* Start of the DOM code */
			//need to try/catch (http://forums.devshed.com/archive/t-110646)
			try {
			
			// Create a new DOM factory, and from that a new DOM builder object
			DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
			DocumentBuilder builder = factory.newDocumentBuilder();
			Document document = builder.newDocument();
			// The root element of our document wil be <purchaseOrder>
			Element rootElement = document.createElement("purchaseOrder");
			document.appendChild(rootElement);

			//create order number element and content and connect to root
			Element orderNumber = document.createElement("orderNumber");
			orderNumber.appendChild(document.createTextNode(ordernumbervalue));
			rootElement.appendChild(orderNumber);
			
			//create orderdate and connect to root
			Element orderDate = document.createElement("orderDate");
			rootElement.appendChild(orderDate);
			
			//create year and connect to orderdate
			Element year = document.createElement("year");
			year.appendChild(document.createTextNode(yearvalue));
			orderDate.appendChild(year);
			
			//create month and connect to orderdate
			Element month = document.createElement("month");
			month.appendChild(document.createTextNode(monthvalue));
			orderDate.appendChild(month);
			
			//create day and connect to orderdate
			Element day = document.createElement("day");
			day.appendChild(document.createTextNode(dayvalue));
			orderDate.appendChild(day);
			
			//create orderedby and connect to root
			Element orderedBy = document.createElement("orderedBy");
			rootElement.appendChild(orderedBy);
			
			Element ordername = document.createElement("name");
			ordername.appendChild(document.createTextNode(ordernamevalue));
			orderedBy.appendChild(ordername);
			
			Element ordercompany = document.createElement("company");
			ordercompany.appendChild(document.createTextNode(ordercompanyvalue));
			orderedBy.appendChild(ordercompany);
			
			Element orderaddress = document.createElement("address");
			orderedBy.appendChild(orderaddress);
			
			Element orderstreet1 = document.createElement("street");
			orderstreet1.appendChild(document.createTextNode(orderstreet1value));
			orderaddress.appendChild(orderstreet1);
			
			Element orderstreet2 = document.createElement("street");
			orderstreet2.appendChild(document.createTextNode(orderstreet2value));
			orderaddress.appendChild(orderstreet2);
			
			Element ordersuburb = document.createElement("suburb");
			ordersuburb.appendChild(document.createTextNode(ordersuburbvalue));
			orderaddress.appendChild(ordersuburb);
			
			Element orderstate = document.createElement("state");
			orderstate.appendChild(document.createTextNode(orderstatevalue));
			orderaddress.appendChild(orderstate);
			
			Element orderpostcode = document.createElement("postcode");
			orderpostcode.appendChild(document.createTextNode(orderpostcodevalue));
			orderaddress.appendChild(orderpostcode);
			
			Element ordercountry = document.createElement("country");
			ordercountry.appendChild(document.createTextNode(ordercountryvalue));
			orderaddress.appendChild(ordercountry);
			
			//create orderedby and connect to root
			Element shipTo = document.createElement("shipTo");
			rootElement.appendChild(shipTo);
			
			Element shiptoname = document.createElement("name");
			shiptoname.appendChild(document.createTextNode(shiptonamevalue));
			shipTo.appendChild(shiptoname);
			
			Element shiptocompany = document.createElement("company");
			shiptocompany.appendChild(document.createTextNode(shiptocompanyvalue));
			shipTo.appendChild(shiptocompany);
			
			Element shiptoaddress = document.createElement("address");
			shipTo.appendChild(shiptoaddress);
			
			Element shiptostreet1 = document.createElement("street");
			shiptostreet1.appendChild(document.createTextNode(shiptostreet1value));
			shiptoaddress.appendChild(shiptostreet1);
			
			Element shiptostreet2 = document.createElement("street");
			shiptostreet2.appendChild(document.createTextNode(shiptostreet2value));
			shiptoaddress.appendChild(shiptostreet2);
			
			Element shiptosuburb = document.createElement("suburb");
			shiptosuburb.appendChild(document.createTextNode(shiptosuburbvalue));
			shiptoaddress.appendChild(shiptosuburb);
			
			Element shiptostate = document.createElement("state");
			shiptostate.appendChild(document.createTextNode(shiptostatevalue));
			shiptoaddress.appendChild(shiptostate);
			
			Element shiptopostcode = document.createElement("postcode");
			shiptopostcode.appendChild(document.createTextNode(shiptopostcodevalue));
			shiptoaddress.appendChild(shiptopostcode);
			
			Element shiptocountry = document.createElement("country");
			shiptocountry.appendChild(document.createTextNode(shiptocountryvalue));
			shiptoaddress.appendChild(shiptocountry);
			
			Element currency = document.createElement("currency");
			currency.appendChild(document.createTextNode(currencyvalue));
			rootElement.appendChild(currency);
			
			Element items = document.createElement("items");
			rootElement.appendChild(items);

			//we can have lots of items, loop here
			for (int i = 0; i < array1.length; i++) {
				Element item = document.createElement("item");
				items.appendChild(item);
				
				Element quantity = document.createElement("quantity");
				quantity.appendChild(document.createTextNode(array1[i][3]));
				item.appendChild(quantity);
				
				Element productCode = document.createElement("productCode");
				productCode.appendChild(document.createTextNode(array1[i][0]));
				item.appendChild(productCode);
				
				Element description = document.createElement("description");
				description.appendChild(document.createTextNode(array1[i][1]));
				item.appendChild(description);
				
				Element unitcost = document.createElement("unitcost");
				unitcost.appendChild(document.createTextNode(array1[i][2]));
				item.appendChild(unitcost);
			}
			
			OutputFormat format = new OutputFormat();
			format.setIndenting(true);
			//format.setEncoding("UTF-8");
			//format.setVersion("1");
			format.setOmitXMLDeclaration(true);
			
			//Some file debugging in here too 
			
			//FileOutputStream outputfile = new FileOutputStream("/usr/home/mwdmeyer/public_html/dca/myfile.txt");
			XMLSerializer serializer = new XMLSerializer(mySocket.getOutputStream(), format);
			//XMLSerializer serializer2 = new XMLSerializer(outputfile, format);

			serializer.serialize(document);
			//serializer2.serialize(document);

			} 
			
			catch (Exception ex) {
				ex.printStackTrace();
			}

			sockOut.flush();
			String fromServer;
			String processedRequest = "";
			while ((fromServer = sockIn.readLine()) != null) {
			//out.println(fromServer);
			
			//if (fromServer.equals("<!--QUIT-->"))
			//break;
			processedRequest += fromServer + "\n";
		}
		
		try {
		 
		 	//Convert a string to XML Found from here
			//Some code from: http://xml.telemessage.com/multialert/post_XML.html
			InputStream xmlin = null;
			xmlin = new ByteArrayInputStream(processedRequest.getBytes()); 
		 	DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
		 	DocumentBuilder db = dbf.newDocumentBuilder();
		 	Document doc = db.parse(xmlin);
	   		traverseTree(doc, out);

		}
		catch (Exception ex) {
				ex.printStackTrace();
		}
 		//clear cart
		clearcart(request);
		
		sockOut.close();
        sockIn.close();
        mySocket.close();

	}
	/**
        **TAKEN FROM LAB04 (some modified)**
		Handles one node of the tree.  It accepts any type of node, and
        will check the node type before processing it.  This function
        is recursive - if one node contains other "sub-nodes", this
        function will call itself again to process the sub-nodes.

        @param currnode the current node
        @param out      where to write the output
	*/
	public void traverseTree(Node currnode, PrintWriter out) {

		
		// If the current node is null, do nothing
		if(currnode == null) {
			return;
		}

		// Find the type of the current node
		int type = currnode.getNodeType();
	
		// Check the node type, and process it accordingly
		switch (type) {
	
			/*
				 * Handle the top-level document node.
				 * Just print out the word "DOCUMENT", and then get the
				 * root element of the document, and process it using
				 * the traverseTree method
			 */
			case Node.DOCUMENT_NODE:{
				traverseTree (((Document)currnode).getDocumentElement(), out);
				break;
			}
		
			/*
				 * Handle an element node
				 * This is the most complex type of node dealt with.
				 * First, print out the name of the element, before
				 * processing any other sub-nodes (i.e. a preorder traversal).
				 * Secondly, check if this element has any attributes, and
				 * if it does, process those next, by calling the traverseTree()
				 * method.
				 * Finally, retrieve the children of this node (if any), and
				 * process them one by one using the traverseTree() method.
			 */
			case Node.ELEMENT_NODE: {
				String elementName = currnode.getNodeName();
			  	
				if (elementName.equals("orderConfirmation") | elementName.equals("summary")) {
				}
				else {
					setresp = setresp + "\n" + "<b>" + elementName + "</b><br />";

				}
		
				if (currnode.hasAttributes()) {
					NamedNodeMap attributes = currnode.getAttributes();
					
					for (int i=0; i < attributes.getLength(); i++) {
				  		Node currattr = attributes.item(i);
				  		traverseTree(currattr, out);
					}
			  	}
		
				NodeList childNodes = currnode.getChildNodes();
			  
				if(childNodes != null) {
					for (int i=0; i < childNodes.getLength() ; i++) {
						traverseTree(childNodes.item(i), out);
					}
			  	}
			  	break;
			}
		
			/*
				 * Handle text nodes.
				 * Trim whitespace off the beginning and end of the text.
				 * Then check whether there is any real text, and if so,
				 * print it out.  This avoids printing out text nodes that
				 * consist of only whitespace characters.
			 */
			case Node.TEXT_NODE: {
				String text = currnode.getNodeValue().trim();
			  	if (text.length() > 0) {
					setresp = setresp + "\n" + text + "<br /><br />";
			  	}
			  	break;
			}
		
		}

		setResponse(setresp);

	}
	
	public void setResponse(String setresp) {
		serverresponse = setresp + "<br />";
	}
	public String getResponse() {
		return serverresponse;
	}

}
