package eu.dnetlib.installer;

import java.io.File;
import java.io.FilenameFilter;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathExpressionException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

/**
 * This class implements a driver web service.
 * @author thanos
 *
 */
public class WebService {
	private static final String BUILD_DIR = "build";
	private static final String BUILD_FILE = "build.xml";
	private static final String RESOLVE_TARGET = "resolve";
	private static final String XPATH = "/ivy-report/dependencies/module/revision/artifacts/artifact[@type = 'jar']/@location";
	private static final String REPORT_DIR = "reports";
	private static final String REPORT_PREFIX = "driver-";
	private static final String REPORT_SUFFIX = "-default.xml";
	private static final String JARS_DIR = "jars";
	private static final String JAR_EXTENSION = ".jar";

	private File baseDir;
	private File distDir;

	/**
	 * Create a new WebService.
	 * @param baseDir the base directory of the web service
	 * @param distDir the directory of published jars
 	 */
	public WebService(File baseDir, File distDir) {
		this.baseDir = baseDir;
		this.distDir = distDir;
	}

	/**
 	 * Resolve the dependencies of a web service by parsing the report of ant resolve.
 	 * @return an array of files(JARs) that this service depends on
 	 * @throws XPathExpressionException if any error occurs while parsing the report
	 */
	public File [] resolveDependencies() throws XPathExpressionException {
		Project project = new Project();
		project.init();
		project.setBaseDir(new File(baseDir + File.separator + BUILD_DIR));
		ProjectHelper.configureProject(project, new File(baseDir + File.separator + BUILD_DIR + File.separator + BUILD_FILE));
		project.executeTarget(RESOLVE_TARGET);
		NodeList dependencyNodes = (NodeList) XPathFactory.newInstance().newXPath().evaluate(XPATH, new InputSource(baseDir + File.separator + BUILD_DIR +
				File.separator + REPORT_DIR + File.separator + REPORT_PREFIX + baseDir.getName() + REPORT_SUFFIX), XPathConstants.NODESET);
		File [] result = new File [dependencyNodes.getLength() + 1];
		for (int i = 0; i < result.length - 1; i++)
			result[i] = new File(dependencyNodes.item(i).getNodeValue());
		result[result.length - 1] = findLastPublishedJar();
		return result;
	}

	/**
	 * Find the last published jar of this web service.
	 * @return the last published jar of the web service
	 */
	private File findLastPublishedJar() {
		File dir = new File(distDir + File.separator + baseDir.getName() + File.separator + JARS_DIR);
		File [] candidates = dir.listFiles(new JarFilter());
		int n = baseDir.getName().length();
		int major = 0;
		int minor = 0;
		int revision = 1;
		for (File candidate : candidates) {
			int currentMajor = Integer.parseInt(candidate.getName().substring(n + 1, n + 2));
			int currentMinor = Integer.parseInt(candidate.getName().substring(n + 3, n + 4));
			int currentRevision = Integer.parseInt(candidate.getName().substring(n + 5, n + 6));
			if (currentMajor >= major) {
				major = currentMajor;
				if (currentMinor >= minor) {
					minor = currentMinor;
					if (currentRevision > revision)
						revision = currentRevision;
				}
			}
		}	
		return new File(dir + File.separator + baseDir.getName() + "-" + major + "." + minor + "." + revision + JAR_EXTENSION);
	}

	private class JarFilter implements FilenameFilter {
		public boolean accept(File dir, String name) {
			return (name.startsWith(baseDir.getName()) && name.endsWith(JAR_EXTENSION));
		}
	}
}

