package eu.ydp.empiria.player.client.module.abstractmodule.structure;

import java.util.HashMap;
import java.util.Map;

import com.google.gwt.xml.client.Document;
import com.google.gwt.xml.client.Element;
import com.google.gwt.xml.client.NodeList;
import com.google.gwt.xml.client.XMLParser;
import com.peterfranza.gwt.jaxb.client.parser.JAXBParser;
import com.peterfranza.gwt.jaxb.client.parser.JAXBParserFactory;

import eu.ydp.empiria.player.client.resources.EmpiriaTagConstants;

public abstract class AbstractModuleStructure<M extends ModuleBean, P extends JAXBParserFactory<M>> {
	
	JAXBParserFactory<M> parserFactory = getParserFactory();
	
	protected M bean;
	
	protected Map<String, Element> feedbacks;
	
	public void createFromXml(String xml) {
		bean = parse(xml);
		prepareStructure();
		prepareFeedbackNodes(xml);
	}	
	
	public M getBean() {
		return bean;
	}
	
	private M parse(String xml){
		return getParser().parse(xml);
	}	
		
	protected JAXBParser<M> getParser() {
		return parserFactory.create();
	}
	
	protected abstract P getParserFactory();
		
	/**
	 * Operates on interaction field ie. for randomize elements, etc.
	 */
	protected abstract void prepareStructure();
	
	/**
	 * Prepares feedbacks map.
	 * Needs to be extended in inheriting module
	 * 
	 * @param xml
	 */
	protected final void prepareFeedbackNodes(String xml) {
		feedbacks = new HashMap<String, Element>();
		Document xmlDocument = parseXML(xml);
		NodeList nodes = getParentNodesForFeedbacks(xmlDocument);
		
		if(nodes != null){
			for(int i = 0; i < nodes.getLength(); i++){
				Element choiceNode = (Element) nodes.item(i);
				Element feedbackNode = getInlineFeedbackNode(choiceNode);
	
				addFeedbackNode(feedbackNode);
			}
		}
	}

	/**
	 * @param xml
	 * @return Document
	 */
	protected Document parseXML(String xml) {
		return XMLParser.parse(xml);
	}
	
	protected abstract NodeList getParentNodesForFeedbacks(Document xmlDocument);

	protected final void addFeedbackNode(Element feedbackNode){
		if(feedbackNode != null){
			String indentifier = feedbackNode.getAttribute(EmpiriaTagConstants.ATTR_IDENTIFIER);
			feedbacks.put(indentifier, feedbackNode);
		}
	}

	protected final Element getInlineFeedbackNode(Element parentNode){
		Element feedbackElement = null;
		NodeList feedbackElements = parentNode.getElementsByTagName(EmpiriaTagConstants.NAME_FEEDBACK_INLINE);

		if(feedbackElements != null && feedbackElements.getLength() > 0){
			feedbackElement = (Element) feedbackElements.item(0);
		}

		return feedbackElement;
	}	
	
	public Element getFeedbackElement(String identifer){
		return feedbacks.get(identifer);
	}	
}

@@ -598,73 +598,10 @@
  %7B%0D%0A
-%09%0D%0A%09JAXBParserFactory%3CM%3E parserFactory = getParserFactory();%0D%0A%09
 %0D%0A
+
 %09pro
@@ -616,19 +616,18 @@
  bean;%0D%0A
-%09
 %0D%0A
+
 %09protect
@@ -662,19 +662,18 @@
 backs;%0D%0A
-%09
 %0D%0A
+
 %09public 
@@ -779,28 +779,26 @@
 es(xml);%0D%0A%09%7D
-%09
 %0D%0A
-%09
 %0D%0A%09public M 
@@ -830,19 +830,18 @@
 n;%0D%0A%09%7D%0D%0A
-%09
 %0D%0A
+
 %09private
@@ -899,21 +899,18 @@
 ml);%0D%0A%09%7D
-%09
 %0D%0A
-%09%09
 %0D%0A%09prote
@@ -952,17 +952,20 @@
 %09return 
-p
+getP
 arserFac
@@ -968,16 +968,18 @@
 rFactory
+()
 .create(
@@ -978,35 +978,34 @@
 .create();%0D%0A%09%7D%0D%0A
-%09
 %0D%0A
+
 %09protected abstr
@@ -1031,20 +1031,18 @@
 ory();%0D%0A
-%09%09
 %0D%0A
+
 %09/**%0D%0A%09 
@@ -1159,19 +1159,18 @@
 ure();%0D%0A
-%09
 %0D%0A
+
 %09/**%0D%0A%09 
@@ -1246,17 +1246,16 @@
 ule%0D%0A%09 *
- 
 %0D%0A%09 * @p
@@ -1481,12 +1481,10 @@
 );%0D%0A
-%09%09
 %0D%0A
+
 %09%09if
@@ -1663,19 +1663,18 @@
 Node);%0D%0A
-%09
 %0D%0A
+
 %09%09%09%09addF
@@ -1848,19 +1848,18 @@
 );%0D%0A%09%7D%0D%0A
-%09
 %0D%0A
+
 %09protect
@@ -2544,20 +2544,18 @@
 ent;%0D%0A%09%7D
-%09
 %0D%0A
-%09
 %0D%0A%09publi
@@ -2643,11 +2643,10 @@
 );%0D%0A
+
 %09%7D
-%09
 %0D%0A%7D%0D

correct wrong initialization order bug 72518