/*
 * This file is part of NixNote/NeighborNote 
 * Copyright 2009 Randy Baumgarte
 * 
 * This file may be licensed under the terms of of the
 * GNU General Public License Version 2 (the ``GPL'').
 *
 * Software distributed under the License is distributed
 * on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
 * express or implied. See the GPL for the specific language
 * governing rights and limitations.
 *
 * You should have received a copy of the GPL along with this
 * program. If not, go to http://www.gnu.org/licenses/gpl.html
 * or write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
 *
*/


package cx.fbn.nevernote.xml;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.trolltech.qt.xml.QDomDocument;
import com.trolltech.qt.xml.QDomDocumentFragment;
import com.trolltech.qt.xml.QDomElement;
import com.trolltech.qt.xml.QDomNode;
import com.trolltech.qt.xml.QDomNodeList;
import com.trolltech.qt.xml.QDomText;

public class XMLInsertHilight {
	private final QDomDocument doc;
	List<String> terms;
	List<QDomNode> oldNodes;
	List<QDomNode> newNodes;
	
	public XMLInsertHilight(QDomDocument d, List<String> t) {
		doc = d;
		terms = t;
		oldNodes = new ArrayList<QDomNode>();
		newNodes = new ArrayList<QDomNode>();
		scanTags();
	}
	public QDomDocument getDoc() {
		for (int i=0; i<oldNodes.size(); i++) {
			oldNodes.get(i).parentNode().replaceChild(newNodes.get(i), oldNodes.get(i));
		}
		return doc;
	}
	// Start looking through the tree.
	private void scanTags() {
//		QDomElement element = doc.firstChildElement();
//		parseChildren(element.firstChild());
		if (doc.hasChildNodes())
			parseNodes(doc.childNodes());
		return;
	}
	
	private void parseNodes(QDomNodeList nodes) {
		for (int i=0; i<nodes.size(); i++) {
			QDomNode node = nodes.at(i);
			if (node.hasChildNodes()) {
				parseNodes(node.childNodes());
			}
			scanWords(node);
		}
}
	
	
	// Parse through individual nodes
	public void parseChildren(QDomNode node) {
		for(; !node.isNull(); node = node.nextSibling()) {
			if (node.hasChildNodes()) {
				QDomNodeList l = node.childNodes();
				for (int i=0; i<l.size(); i++)
					parseChildren(l.at(i));
			}
			if (node.isText()) {
				scanWords(node);
			}
		}
	}
	
	// We found a text node, so we need to search for things to hilight
	private void scanWords(QDomNode node) { 
		String value = node.nodeValue();
		
		QDomDocumentFragment fragment = doc.createDocumentFragment();
		boolean matchFound = false;
		int previousPosition = 0;
		String valueEnd = "";
	
		String regex = buildRegex();
			
		Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
		Matcher matcher = pattern.matcher(value);
			
		while (matcher.find()) {
			matchFound = true;
			String valueStart = "";
			int start = matcher.start();
			int end = matcher.end();
			if (value.substring(start).startsWith(" "))
					start++;
				if (value.substring(start, end).endsWith(" "))
					end--;
			
			if (matcher.start() > 0) {
				valueStart = value.substring(previousPosition,start); 
			} 
			String valueMiddle = value.substring(start, end);
			valueEnd = "";
			if (matcher.end() < value.length()) {
				valueEnd = value.substring(end);
			}
			
			previousPosition = end;
			if (!valueStart.equals("")) {
				QDomText startText = doc.createTextNode(valueStart);
				fragment.appendChild(startText);
			}
			
			QDomElement hilight = doc.createElement("en-hilight");
			hilight.appendChild(doc.createTextNode(valueMiddle));
			fragment.appendChild(hilight);
		}
		if (matchFound) {
			if (previousPosition != value.length()) {
				QDomText endText = doc.createTextNode(valueEnd);
				fragment.appendChild(endText);
			}
			newNodes.add(fragment);
			oldNodes.add(node);
		}
	}
	
	
	private String buildRegex() {
		StringBuffer regex = new StringBuffer();
		
		// Remove any empty terms of it screws things up later
		for (int j=terms.size()-1; j>=0; j--) {
			if (terms.get(j).trim().equals(""))
				terms.remove(j);
		}
		
		for (int i=0; i<terms.size(); i++) {
			String term = terms.get(i);
			if (term.indexOf("*") > -1) {
				term = term.replace("*", "");
			}/* else {
				term = "\\b"+term+"\\b";
			}*/
			regex.append(term);
			if (i<terms.size()-1)
				regex.append("|"); 
		}
		
		return regex.toString();
	}
	

}
