package org.eclipse.europa.tools.webgen;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;

import org.eclipse.europa.tools.utils.CommonXML;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class CheckForFeatureInSiteXml {

	public static void main(String[] args) throws IOException, SAXException {
		String feature = args[0];
		String sitefilename = args[1] + "/site.xml";
		Map<String, Map<String, Object>> results = new Hashtable<String, Map<String, Object>>();
		(new CheckForFeatureInSiteXml()).process(new File(feature), new File(
				sitefilename), results);
		for (Iterator iterator = results.keySet().iterator(); iterator
				.hasNext();) {
			String project = (String) iterator.next();
			System.out.print(project + " --> ");
			for(Iterator iter2 = results.get(project).keySet().iterator(); iter2.hasNext();) {
				String id = (String) iter2.next();
				System.out.print(id + ",");
			}
			System.out.println();
		}
	}

	private Map<String, Boolean> siteInfo = new Hashtable<String, Boolean>();

	private Map<String, Map<String, Object>> featuresInfo = new Hashtable<String, Map<String, Object>>();

	public void process(File featuresDir, File siteXml,
			Map<String, Map<String, Object>> results) throws IOException, SAXException {
		readSiteXml(siteXml);
		readFeaturesFiles(featuresDir);
		compareSiteXml_to_FeaturesFiles();
		compareFeaturesFiles_to_SiteXml();
		reportMissingFromSiteXml(results);
		reportMissingFromFeaturesFiles(results);
	}

	private void reportMissingFromSiteXml(Map<String, Map<String, Object>> results) {
		for (Iterator iterator = this.featuresInfo.keySet().iterator(); iterator
				.hasNext();) {
			String id = (String) iterator.next();
			if (!((Boolean) (featuresInfo.get(id).get("seen_in_site")))
					.booleanValue()) {
				String project = (String) featuresInfo.get(id).get("project");
				Map<String, Object> res = new Hashtable<String, Object>();
				if( results.containsKey(project) )
					res = results.get(project);
				res.put(id, new Boolean(true));
				results.put(project, res);
			}
		}
	}

	private void reportMissingFromFeaturesFiles(Map<String, Map<String, Object>> results) {
		for (Iterator iterator = this.siteInfo.keySet().iterator(); iterator
				.hasNext();) {
			String id = (String) iterator.next();
			if (!siteInfo.get(id).booleanValue()) {
				String project = "";
				Map<String, Object> res = new Hashtable<String, Object>();
				if( results.containsKey(project) )
					res = results.get(project);
				res.put(id, new Boolean(true));
				results.put(project, res);
			}
		}
	}

	private void compareFeaturesFiles_to_SiteXml() {
		for (Iterator iterator = this.featuresInfo.keySet().iterator(); iterator
				.hasNext();) {
			String id = (String) iterator.next();
			if (siteInfo.containsKey(id)) {
				featuresInfo.get(id).put("seen_in_site", new Boolean(true));
			}
		}
	}

	private void compareSiteXml_to_FeaturesFiles() {
		for (Iterator iterator = this.siteInfo.keySet().iterator(); iterator
				.hasNext();) {
			String id = (String) iterator.next();
			if (featuresInfo.containsKey(id)) {
				siteInfo.put(id, new Boolean(true));
			}
		}
	}

	private void readFeaturesFiles(File featuresDir) throws IOException,
			SAXException {
		Pattern p1 = Pattern
				.compile("\\-*\\s+Project:\\s+([\\w\\s_\\-\\.,]+)\\s+Responsible:\\s+(\\w+)");
		FileInputStream updateMirrorAll = new FileInputStream(new File(
				featuresDir, "updateMirrorAll.xml"));
		try {
			DocumentBuilder documentBuilder = CommonXML.getDocumentBuilder();
			Document updateMirrorAllDom = documentBuilder
					.parse(updateMirrorAll);

			NodeList antNodeList = updateMirrorAllDom
					.getElementsByTagName("ant");
			int nNodes = antNodeList.getLength();
			for (int i = 0; i < nNodes; i++) {
				Node node = antNodeList.item(i);
				NamedNodeMap attributeMap = node.getAttributes();
				Node antfileAttribute = attributeMap.getNamedItem("antfile");
				String id = antfileAttribute.getNodeValue();
				if (id.startsWith("features-")) {
					FileInputStream featureXml = new FileInputStream(new File(
							featuresDir, id));
					System.out.println("processing " + id);
					try {
						Document featureXmlDom = documentBuilder
								.parse(featureXml);

						NodeList echoNodeList = featureXmlDom
								.getElementsByTagName("echo");
						Node node3 = echoNodeList.item(0);
						NamedNodeMap attributeMap3 = node3.getAttributes();
						Node messageAttribute = attributeMap3
								.getNamedItem("message");
						String message = messageAttribute.getNodeValue();
						Matcher m1 = p1.matcher(message);
						m1.find();
						String projectName = m1.group(1);

						NodeList propertyNodeList = featureXmlDom
								.getElementsByTagName("property");
						int nNodes2 = propertyNodeList.getLength();
						for (int j = 0; j < nNodes2; j++) {
							Node node2 = propertyNodeList.item(j);
							NamedNodeMap attributeMap2 = node2.getAttributes();
							Node nameAttribute = attributeMap2
									.getNamedItem("name");
							Node valueAttribute = attributeMap2
									.getNamedItem("value");
							String name = nameAttribute.getNodeValue();
							String value = valueAttribute.getNodeValue();
							if (name.equals("featureId")) {
								Map<String, Object> rec = new Hashtable<String, Object>();
								rec.put("project", projectName);
								rec.put("seen_in_site", new Boolean(false));
								featuresInfo.put(value, rec);
							}
						}
					} finally {
						featureXml.close();
					}
				}
			}
		} finally {
			updateMirrorAll.close();
		}
	}

	private void readSiteXml(File siteXml) throws IOException, SAXException {
		FileInputStream oldFile = new FileInputStream(siteXml);
		try {
			DocumentBuilder documentBuilder = CommonXML.getDocumentBuilder();
			Document oldDom = documentBuilder.parse(oldFile);

			NodeList oldNodeList = oldDom.getElementsByTagName("feature");

			int nNodes = oldNodeList.getLength();

			for (int i = 0; i < nNodes; i++) {
				Node node = oldNodeList.item(i);
				NamedNodeMap attributeMap = node.getAttributes();
				Node oldIdAttribute = attributeMap.getNamedItem("id");
				String id = oldIdAttribute.getNodeValue();
				siteInfo.put(id, new Boolean(false));
			}
		} finally {
			oldFile.close();
		}
	}

}
