package com.udapsoft.waf.system.handler.dao;

import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.List;

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

import org.w3c.dom.Document;
import org.w3c.dom.Element;
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 EventMappingDAO {

	public static final String EVENT_MAPPING = "EVENT-MAPPING";
	public static final String SCREEN = "SCREEN";
	public static final String EVENT = "EVENT";
	public static final String BIZ = "BIZ";

	public EventMappingDAO() {
	}

	private static Element loadDocument(Class<?> pclass) {
		Document doc = null;
		Element root = null;
		try {
			InputStream is = null;
			String encoding = "";
			try {
				byte[] bytes = new byte[100];
				is = pclass.getResourceAsStream("event_mapping.xml");
				if (is.read(bytes) != -1) {
					encoding = new String(bytes);
					if (encoding.indexOf("encoding=\"") > 0) {
						encoding = encoding.substring(encoding.indexOf("encoding=\"") + 10, encoding.length());
					} else if (encoding.indexOf("'encoding='") > 0) {
						encoding = encoding.substring(encoding.indexOf("'encoding='"), encoding.length());
					}

					if (encoding.indexOf("\"") > 0) {
						encoding = encoding.substring(0, encoding.indexOf("\""));
					} else if (encoding.indexOf("'") > 0) {
						encoding = encoding.substring(0, encoding.indexOf("\""));
					}
				}

			} catch (Exception e) {
				System.err.println("EventMappingDAO encoding extract error: " + e);
				
			} finally {
				if (is != null)
					is.close();
			}

			is = pclass.getResourceAsStream("event_mapping.xml");
			InputSource xmlInp = new InputSource(is);
			xmlInp.setEncoding(encoding);
			DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
			DocumentBuilder parser = docBuilderFactory.newDocumentBuilder();
			doc = parser.parse(xmlInp);
			root = doc.getDocumentElement();
			root.normalize();

		} catch (SAXParseException err) {
			System.err.println("EventMappingDAO ** Parsing error, line " + err.getLineNumber() + ", uri " + err.getSystemId());
			System.err.println("EventMappingDAO error: " + err.getMessage());
			
		} catch (SAXException e) {
			System.err.println("EventMappingDAO error: " + e);
			
		} catch (MalformedURLException mfx) {
			System.err.println("EventMappingDAO error: " + mfx);
			
		} catch (IOException e) {
			System.err.println("EventMappingDAO error: " + e);
			
		} catch (Exception pce) {
			System.err.println("EventMappingDAO error: " + pce);
		}
		
		return root;
	}

	public static EventMappings loadEventMappings(Class<?> pclass) {
		Element root = loadDocument(pclass);
		if (root != null)
			return getEventMappings(root);
		else
			return null;
	}

	private static EventMappings getEventMappings(Element root) {
		EventMappings eventMappings = new EventMappings();
		NodeList screenNodeList = root.getElementsByTagName(SCREEN);

		for (int i = 0; i < screenNodeList.getLength(); i++) {

			Node screenNode = screenNodeList.item(i);
			if (screenNode != null) {

				String screenName = null;
				String eventName = null;
				List<String> bizList = null;
				screenName = ((Element) screenNode).getAttribute("name");
				NodeList eventNodeList = ((Element) screenNode).getElementsByTagName(EVENT);

				for (int j = 0; j < eventNodeList.getLength(); j++) {

					bizList = new ArrayList<String>();
					Node eventNode = eventNodeList.item(j);
					if (screenNode != null) {
						eventName = ((Element) eventNode).getAttribute("name");
						NodeList bizNodeList = ((Element) eventNode).getElementsByTagName(BIZ);
						for (int k = 0; k < bizNodeList.getLength(); k++) {

							Node bizNode = bizNodeList.item(k);
							if (bizNode != null) {
								String className = ((Element) bizNode).getAttribute("class");
								bizList.add(className);
							}
						}
						EventMapping eventMapping = new EventMapping(screenName, eventName, bizList);
						eventMappings.put(screenName, eventName, eventMapping);
					}
				}
			}
		}
		return eventMappings;
	}
}