package pt.link.utils.importer;
import java.io.File;
import java.util.Iterator;
import java.util.LinkedList;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;


public class Merger {
	protected Document document;
	
	public String getXPathHierarchy(Node _node){
		StringBuffer strBuf = new StringBuffer("//");
		
		LinkedList hierarchy = new LinkedList();
		hierarchy.add(_node.getParentNode());
		while(   ((Node)hierarchy.getFirst()).getParentNode() != null   ){
			hierarchy.addFirst(((Node)hierarchy.getFirst()).getParentNode());
		}
		hierarchy.addLast(_node);
		hierarchy.removeFirst();
		
		for(Iterator it = hierarchy.iterator();it.hasNext();){
			Node node = (Node)it.next();node.getPrefix();
			String nodeName = node.getNodeName();
			if(nodeName.indexOf(":") != -1)
				nodeName = nodeName.substring(nodeName.indexOf(":") + 1);
			strBuf.append( nodeName);
			
			if(node.getAttributes().getNamedItem("id") != null){
				strBuf.append("[@id='" + node.getAttributes().getNamedItem("id").getNodeValue()  + "']");
			}
			
			if(it.hasNext())
				strBuf.append("/");
		}
		return strBuf.toString();	
	}
	
	public void parseDocument(Document document2) throws Exception {
		NodeList doc2NodeList = org.apache.xpath.XPathAPI.selectNodeList(document2, "//*[@locale]");
		for(int i=0; i<doc2NodeList.getLength(); i++){
			Node doc2Node = doc2NodeList.item(i);
			String xPathHierarchy = getXPathHierarchy(doc2NodeList.item(i));
//			System.out.println(xPathHierarchy);
			
			NodeList doc1NodeList = org.apache.xpath.XPathAPI.selectNodeList(document, xPathHierarchy);
			
//			for(int j=0;j<doc1NodeList.getLength();j++){
			if(doc1NodeList.getLength() > 0) {
				Node imported = document.importNode(doc2Node, true);
				doc1NodeList.item(0).getParentNode().insertBefore(imported, doc1NodeList.item(0));
			}
		}
//		System.out.println("-----------------------");
	}
	
	public void mergeFiles(File file1, File file2, StreamResult result) throws Exception{
		DocumentBuilderFactory factory =
            DocumentBuilderFactory.newInstance();
		
		DocumentBuilder builder;
		try {
			builder = factory.newDocumentBuilder();
			
			document = builder.parse(file1);
			Document document2= builder.parse(file2);
			
			parseDocument( document2);
			TransformerFactory tFactory =
			       TransformerFactory.newInstance();

			
			Transformer transformer = tFactory.newTransformer();
			
			
			DOMSource source = new DOMSource(document);
			transformer.transform(source, result);
			
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		} 
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
//		System.out.println("...");
		File file1 = new File (args[0]);
//		System.out.println(args[0]);
		
		File file2 = new File (args[1]);
		
		Merger merger; //
		merger = new Merger();
		
		File outFile;
		StreamResult result;
		if(args.length > 2){
			outFile = new File(args[2]);
			result = new StreamResult(outFile);
		}
		else
			result = new StreamResult(System.out);
		try {
			merger.mergeFiles(file1, file2, result);
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		

	}
}
