/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.taverna.commandline;

import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URI;
import java.net.URL;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.comparator.NameFileComparator;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;

import org.apache.taverna.commandline.WorkflowTestSuite.Workflows;
import org.apache.taverna.scufl2.api.container.WorkflowBundle;
import org.apache.taverna.scufl2.api.io.WorkflowBundleIO;
import org.apache.taverna.scufl2.rdfxml.RDFXMLReader;

/**
 * Regression tests for Taverna Command Line Tool.
 */
@RunWith(WorkflowTestSuite.class)
public class TavernaCommandLineTest {

	private static String baseVersion = "2.4.0";
	private static boolean baseVersionReleased = true;

	private static String testVersion = "3.0.1-SNAPSHOT";
	private static boolean testVersionReleased = false;
	private static boolean testVersionSupportsScufl2 = true;

	private static String script = "executeworkflow.sh";
	private static String baseName = "taverna-commandline-" + baseVersion;
	private static String testName = "taverna-command-line-" + testVersion;
	private static String releasedLocation = "https://launchpad.net/taverna/t2/";
	private static String unreleasedLocation = "http://build.mygrid.org.uk/ci/job/t3-taverna-commandline-product/lastSuccessfulBuild/net.sf.taverna.t2$taverna-commandline/artifact/net.sf.taverna.t2/taverna-commandline/";

	private static String baseVersionLocation = (baseVersionReleased ? releasedLocation
			: unreleasedLocation) + baseVersion + "/+download/" + baseName + ".zip";
	private static String testVersionLocation = (testVersionReleased ? releasedLocation
			: unreleasedLocation)
			+ testVersion
			+ "/"
			+ testName
			+ (testVersionReleased ? ".zip" : "-bin.zip");

	private static String baseCommand;
	private static String testCommand;

	private static File buildDirectory;

	private File workflowDirectory;
	private File baseOutput;
	private File testOutput;
	private boolean secure;
	private List<File> inputs;
	private String ignorePort;
	private String message;

	public TavernaCommandLineTest(File workflowDirectory) throws Exception {
		this.workflowDirectory = workflowDirectory;
		if (buildDirectory == null) {
			String buildDirectoryLocation = System.getProperty("buildDirectory");
			if (buildDirectoryLocation == null) {
				buildDirectoryLocation = System.getProperty("user.dir")
						+ System.getProperty("file.separator") + "target";
			}
			buildDirectory = new File(buildDirectoryLocation);
			buildDirectory.mkdirs();
		}
		if (baseCommand == null) {
			File commandDirectory = new File(buildDirectory, baseName);
			if (!commandDirectory.exists()) {
				System.out.println("Fetching " + baseName);
				fetchTaverna(baseVersionLocation, baseName);
			}
			baseCommand = new File(baseName, script).getPath();
		}
		if (testCommand == null) {
			File commandDirectory = new File(buildDirectory, testName);
			if (!commandDirectory.exists()) {
				System.out.println("Fetching " + testName);
				fetchTaverna(testVersionLocation, testName);
			}
			testCommand = new File(testName, script).getPath();
		}
		File outputsDirectory = new File(buildDirectory, "test-outputs");
		baseOutput = new File(outputsDirectory, workflowDirectory.getName() + "-" + baseVersion);
		testOutput = new File(outputsDirectory, workflowDirectory.getName() + "-" + testVersion);
		secure = workflowDirectory.getName().startsWith("secure");
		inputs = getInputs();
		ignorePort = getIgnorePort();
		message = "Running {0} with version {1}";
	}

	@Workflows
	public static List<File> workflows() {
		List<File> workflows = new ArrayList<File>();
		for (File workflowDirectory : getResources("workflows")) {
			workflows.add(workflowDirectory);
		}
		for (File workflowDirectory : getResources("myexperiment")) {
			workflows.add(workflowDirectory);
		}
		return workflows;
	}

	@Before
	public void setup() throws Exception {
		if (!baseOutput.exists()) {
			if (baseVersion.equals("2.3.0") && workflowDirectory.getName().equals("tool"))
				return;// version 2.3.0 is missing tool plugin
			String workflow = getWorkflow().toASCIIString();
			System.out.println(MessageFormat.format(message, workflow, baseVersion)
					+ (inputs.size() > 0 ? " using input values" : ""));
			runWorkflow(baseCommand, workflow, baseOutput, true, secure, false);
			assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
					baseOutput.exists());
		}
	}

	public boolean testExcluded() {
		// version 3.0.0 is missing biomoby activity
		if (testVersion.startsWith("3.") && workflowDirectory.getName().contains("biomoby"))
			return true;
		// version 3.0.0 is missing tool activity
		if (testVersion.startsWith("3.")
				&& workflowDirectory.getName().equals("unix_external_tools_with_zip_and_unzip"))
			return true;
		if (testVersion.startsWith("3.")
				&& workflowDirectory.getName().equals("unix_numerically_adding_two_values"))
			return true;
		if (testVersion.startsWith("3.")
				&& workflowDirectory.getName().equals("unix_tool_service_using_string_replacement"))
			return true;
		// version 3.0.0 is missing looping configuration
		if (testVersion.startsWith("3.")
				&& workflowDirectory.getName().equals("ebi_interproscan_newservices"))
			return true;
		if (testVersion.startsWith("3.")
				&& workflowDirectory.getName().equals("biomartandembossanalysis"))
			return true;
		return false;
	}

	@Test
	public void testWorkflowWithoutInputs() throws Exception {
		assumeTrue(!testExcluded());
		assumeTrue(baseOutput.exists());
		assumeTrue(inputs.isEmpty());
		FileUtils.deleteDirectory(testOutput);
		String workflow = getWorkflow().toASCIIString();
		System.out.println(MessageFormat.format(message, workflow, testVersion));
		runWorkflow(testCommand, workflow, testOutput, true, secure, false);
		assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
				testOutput.exists());
		assertOutputsEquals(baseOutput, testOutput);
	}

	@Test
	public void testWorkflowWithInputValues() throws Exception {
		assumeTrue(!testExcluded());
		assumeTrue(baseOutput.exists());
		assumeTrue(inputs.size() > 0);
		FileUtils.deleteDirectory(testOutput);
		String workflow = getWorkflow().toASCIIString();
		System.out.println(MessageFormat.format(message, workflow, testVersion)
				+ " using input values");
		runWorkflow(testCommand, workflow, testOutput, true, secure, false);
		assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
				testOutput.exists());
		assertOutputsEquals(baseOutput, testOutput);
	}

	@Test
	public void testWorkflowWithInputFiles() throws Exception {
		assumeTrue(!testExcluded());
		assumeTrue(baseOutput.exists());
		assumeTrue(inputs.size() > 0);
		FileUtils.deleteDirectory(testOutput);
		String workflow = getWorkflow().toASCIIString();
		System.out.println(MessageFormat.format(message, workflow, testVersion)
				+ " using input files");
		runWorkflow(testCommand, workflow, testOutput, false, secure, false);
		assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
				testOutput.exists());
		assertOutputsEquals(baseOutput, testOutput);
	}

	@Test
	@Ignore
	public void testWorkflowWithDatabase() throws Exception {
		assumeTrue(!testExcluded());
		assumeTrue(baseOutput.exists());
		assumeTrue(inputs.size() > 0);
		FileUtils.deleteDirectory(testOutput);
		String workflow = getWorkflow().toASCIIString();
		System.out
				.println(MessageFormat.format(message, workflow, testVersion) + " using database");
		runWorkflow(testCommand, workflow, testOutput, true, secure, true);
		assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
				testOutput.exists());
		assertOutputsEquals(baseOutput, testOutput);
	}

	@Test
	public void testScufl2Workflow() throws Exception {
		assumeTrue(!testExcluded());
		assumeTrue(baseOutput.exists());
		assumeTrue(testVersionSupportsScufl2);

		FileUtils.deleteDirectory(testOutput);
		String workflow = getScufl2Workflow().toASCIIString();
		System.out.println(MessageFormat.format(message, workflow, testVersion)
				+ (inputs.size() > 0 ? " using input values" : ""));
		runWorkflow(testCommand, workflow, testOutput, true, secure, true);
		assertTrue(String.format("No output produced for %s", workflowDirectory.getName()),
				testOutput.exists());
		assertOutputsEquals(baseOutput, testOutput);
	}

	private synchronized void runWorkflow(String command, String workflow, File outputsDirectory,
			boolean inputValues, boolean secure, boolean database) throws Exception {
		ProcessBuilder processBuilder = new ProcessBuilder("sh", command);
		processBuilder.redirectErrorStream(true);
		processBuilder.directory(buildDirectory);
		List<String> args = processBuilder.command();
		for (File input : inputs) {
			if (inputValues) {
				args.add("-inputvalue");
				args.add(input.getName());
				args.add(IOUtils.toString(new FileReader(input)));
			} else {
				args.add("-inputfile");
				args.add(input.getName());
				args.add(input.getAbsolutePath());
			}
		}
		args.add("-outputdir");
		args.add(outputsDirectory.getPath());
		if (secure) {
			args.add("-cmdir");
			args.add(getClass().getResource("/security").getFile());
			args.add("-cmpassword");
		}
		if (database) {
			args.add("-embedded");
		}
		args.add(workflow);
		Process process = processBuilder.start();
		if (secure) {
			PrintStream outputStream = new PrintStream(process.getOutputStream());
			outputStream.println("test");
			outputStream.flush();
		}
		waitFor(process);
	}

	private URI getWorkflow() throws Exception {
		File workflow = new File(workflowDirectory, workflowDirectory.getName() + ".t2flow");
		if (!workflow.exists()) {
			workflow = new File(workflowDirectory, workflowDirectory.getName() + ".url");
			return new URI(IOUtils.toString(new FileReader(workflow)));
		}
		return workflow.toURI();
	}

	private URI getScufl2Workflow() throws Exception {
		File workflow = new File(buildDirectory, workflowDirectory.getName() + ".wfbundle");
		// if (!workflow.exists()) {
		WorkflowBundleIO workflowBundleIO = new WorkflowBundleIO();
		WorkflowBundle bundle = workflowBundleIO.readBundle(getWorkflow().toURL(), null);
		workflowBundleIO.writeBundle(bundle, workflow,
				RDFXMLReader.APPLICATION_VND_TAVERNA_SCUFL2_WORKFLOW_BUNDLE);
		// }
		return workflow.toURI();
	}

	private synchronized int waitFor(Process process) throws IOException {
		while (true) {
			try {
				wait(500);
			} catch (InterruptedException e) {
			}
			IOUtils.copy(process.getInputStream(), System.out);
			try {
				return process.exitValue();
			} catch (IllegalThreadStateException e) {
			}
		}
	}

	private void assertOutputsEquals(File directory1, File directory2) {
		File[] directory1Files = directory1.listFiles();
		File[] directory2Files = directory2.listFiles();
		// assert directories contain same number of files
		assertEquals(String.format("%s has %s files but %s has %s files", directory1.getName(),
				directory1Files.length, directory2.getName(), directory2Files.length),
				directory1Files.length, directory2Files.length);
		// sort files in directory
		Arrays.sort(directory1Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
		Arrays.sort(directory2Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
		for (int i = 0; i < directory1Files.length; i++) {
			assertFilesEqual(directory1Files[i], directory2Files[i], !directory1Files[i].getName()
					.equals(ignorePort));
		}
	}

	private void assertDirectoriesEquals(File directory1, File directory2, boolean checkFileContents) {
		if (directory1.exists()) {
			assertTrue(String.format("%s exists but %s does not", directory1, directory2),
					directory2.exists());
		} else {
			assertFalse(String.format("%s does not exists but %s does", directory1, directory2),
					directory2.exists());
		}
		File[] directory1Files = directory1.listFiles();
		File[] directory2Files = directory2.listFiles();
		// assert directories contain same number of files
		assertEquals(String.format("%s has %s files but %s has %s files", directory1.getName(),
				directory1Files.length, directory2.getName(), directory2Files.length),
				directory1Files.length, directory2Files.length);
		// sort files in directory
		Arrays.sort(directory1Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
		Arrays.sort(directory2Files, NameFileComparator.NAME_SYSTEM_COMPARATOR);
		for (int i = 0; i < directory1Files.length; i++) {
			assertFilesEqual(directory1Files[i], directory2Files[i], checkFileContents);
		}
	}

	private void assertFilesEqual(File file1, File file2, boolean checkFileContents) {
		if (file1.isHidden()) {
			assertTrue(String.format("%s is hidden but %s is not", file1, file2), file2.isHidden());
		} else {
			assertFalse(String.format("%s is not hidden but %s is", file1, file2), file2.isHidden());
			assertEquals(file1.getName(), file2.getName());
			if (file1.isDirectory()) {
				assertTrue(String.format("%s is a directory but %s is not", file1, file2),
						file2.isDirectory());
				assertDirectoriesEquals(file1, file2, checkFileContents);
			} else {
				assertFalse(String.format("%s is not a directory but %s is", file1, file2),
						file2.isDirectory());
				if (isZipFile(file1)) {
					assertZipFilesEqual(file1, file2);
				} else if (checkFileContents) {
					assertEquals(String.format("%s is a different length to %s", file1, file2),
							file1.length(), file2.length());
					try {
						byte[] byteArray1 = IOUtils.toByteArray(new FileReader(file1));
						byte[] byteArray2 = IOUtils.toByteArray(new FileReader(file2));
						assertArrayEquals(String.format("%s != %s", file1, file2), byteArray1,
								byteArray2);
					} catch (FileNotFoundException e) {
						fail(e.getMessage());
					} catch (IOException e) {
						fail(e.getMessage());
					}
				}
			}
		}
	}

	private void assertZipFilesEqual(File file1, File file2) {
		ZipFile zipFile1 = null;
		ZipFile zipFile2 = null;
		try {
			zipFile1 = new ZipFile(file1);
			zipFile2 = new ZipFile(file2);
		} catch (Exception e) {
			assertTrue(String.format("%s and %s are not both zip files"), zipFile1 == null);
		}
		if (zipFile1 != null && zipFile2 != null) {
			Enumeration<? extends ZipEntry> entries1 = zipFile1.entries();
			Enumeration<? extends ZipEntry> entries2 = zipFile2.entries();
			while (entries1.hasMoreElements()) {
				assertTrue(entries2.hasMoreElements());
				ZipEntry zipEntry1 = entries1.nextElement();
				ZipEntry zipEntry2 = entries2.nextElement();
				assertEquals(
						String.format("%s and %s are not both directories", zipEntry1, zipEntry2),
						zipEntry1.isDirectory(), zipEntry2.isDirectory());
				assertEquals(String.format("%s and %s have different names", zipEntry1, zipEntry2),
						zipEntry1.getName(), zipEntry2.getName());
				assertEquals(String.format("%s and %s have different sizes", zipEntry1, zipEntry2),
						zipEntry1.getSize(), zipEntry2.getSize());
				try {
					byte[] byteArray1 = IOUtils.toByteArray(zipFile1.getInputStream(zipEntry1));
					byte[] byteArray2 = IOUtils.toByteArray(zipFile2.getInputStream(zipEntry2));
					assertArrayEquals(String.format("%s != %s", zipEntry1, zipEntry2), byteArray1,
							byteArray2);
				} catch (IOException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			assertFalse(entries2.hasMoreElements());
		}
	}

	private boolean isZipFile(File file) {
		try {
			new ZipFile(file);
			return true;
		} catch (Exception e) {
			return false;
		}
	}

	private static File[] getResources(String directory) {
		return new File(TavernaCommandLineTest.class.getResource("/" + directory).getFile())
				.listFiles();
	}

	private List<File> getInputs() {
		File inputsDirectory = new File(workflowDirectory, "inputs");
		if (inputsDirectory.exists() && inputsDirectory.isDirectory()) {
			return Arrays.asList(inputsDirectory.listFiles());
		}
		return Collections.emptyList();
	}

	private String getIgnorePort() throws Exception {
		File ignorePort = new File(workflowDirectory, "ignorePort");
		if (ignorePort.exists()) {
			return IOUtils.toString(new FileReader(ignorePort));
		}
		return "";
	}

	private void fetchTaverna(String location, String name) throws Exception {
		File zipFile = new File(buildDirectory, name + ".zip");
		IOUtils.copy(new URL(location).openStream(), new FileOutputStream(zipFile));
		ProcessBuilder processBuilder = new ProcessBuilder("unzip", "-q", name);
		processBuilder.redirectErrorStream(true);
		processBuilder.directory(buildDirectory);
		System.out.println(processBuilder.command());
		Process process = processBuilder.start();
		waitFor(process);
	}

}
