/**
 * <copyright>
 *
 * Copyright (c) 2014 Obeo and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *   Obeo - initial API and implementation 
 *
 * </copyright>
 */
package org.eclipse.ocl.examples.standalone.validity;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.ocl.examples.emf.validation.validity.RootNode;
import org.eclipse.ocl.examples.emf.validation.validity.export.IValidityExporter;
import org.eclipse.ocl.examples.emf.validation.validity.export.IValidityExporterDescriptor;
import org.eclipse.ocl.examples.emf.validation.validity.export.ValidityExporterRegistry;
import org.eclipse.ocl.examples.pivot.validation.PivotEObjectValidator.ValidationAdapter;
import org.eclipse.ocl.examples.standalone.StandaloneApplication;
import org.eclipse.ocl.examples.standalone.StandaloneCommand;
import org.eclipse.ocl.examples.standalone.StandaloneResponse;
import org.eclipse.ocl.examples.standalone.messages.StandaloneMessages;
import org.eclipse.ocl.examples.xtext.completeocl.ui.commands.LoadCompleteOCLResourceHandler.Helper;

/**
 * The ValidateCommand provides model validation.
 */
public class ValidateCommand extends StandaloneCommand
{
	private static final Logger logger = Logger.getLogger(ValidateCommand.class);

	protected static final class ExporterComparator implements Comparator<IValidityExporterDescriptor>
	{
		public static final @NonNull ExporterComparator INSTANCE = new ExporterComparator();

		@Override
		public int compare(IValidityExporterDescriptor o1, IValidityExporterDescriptor o2) {
			String n1 = o1.getExporterType();
			String n2 = o2.getExporterType();
			return n1.compareTo(n2);
		}
	}

	/**
	 * An optional argument to specify which exporter should be used. By
	 * default, the �txt� exporter will be used, exporting a textual report of
	 * the validation.
	 */
	public static class ExporterToken extends StringToken
	{
		public ExporterToken() {
			super("-exporter", StandaloneMessages.ValidateCommand_Exporter_Help);
		}
		
		public boolean check(@NonNull List<String> strings) {
			return getExporter(strings) != null;
		}

		public @Nullable String getArgsHelp() {
			List<IValidityExporterDescriptor> exporters = new ArrayList<IValidityExporterDescriptor>(ValidityExporterRegistry.INSTANCE.getRegisteredExtensions());
			Collections.sort(exporters, ExporterComparator.INSTANCE);
			StringBuilder s = new StringBuilder();
			for (IValidityExporterDescriptor exporter : exporters) {
				if (s.length() > 0) {
					s.append("|");
				}
				s.append(exporter.getExporterType());
			}
			return s.toString();
		}

		private @Nullable IValidityExporter getExporter(@NonNull List<String> strings) {
			if (strings.size() <= 0) {
				return null;
			}
			String string = strings.get(0);
			return ValidityExporterRegistry.INSTANCE.getExporter(string);
		}

		public @Nullable IValidityExporter getExporter(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			if (strings == null) {
				return null;
			}
			return getExporter(strings);
		}


		/**
		 * Gets the validation exporter corresponding to the argument read after the
		 * <b>-report</b> argument.
		 * 
		 * @return The validation exporter.
		 */
//		public AbstractExporter getExporter() {
//			return exporter;
//		}
	}

	/**
	 * A mandatory argument key of the model file path. This argument key must
	 * be followed by the model file path.
	 */
	public static class ModelToken extends StringToken
	{
		public ModelToken() {
			super("-model", StandaloneMessages.ValidateCommand_Model_Help);
		}
		
		public boolean check(@NonNull List<String> strings) {
			return getModelFileName(strings) != null;
		}

		public @Nullable String getArgsHelp() {
			return "<file-name>";
		}

		private @Nullable String getModelFileName(@NonNull List<String> strings) {
			if (strings.size() <= 0) {
				return null;
			}
			String string = strings.get(0);
			return getCheckedFileName(string);
		}

		public @Nullable String getModelFileName(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			if (strings == null) {
				return null;
			}
			return getModelFileName(strings);
		}

		/**
		 * Gets the absolute path to the model file deduced from the value specified
		 * after the argument <b>-model</b>.
		 * 
		 * @return the model path as a String.
		 */
//		public IPath getModelFilePath() {
//			return modelPath;
//		}
	}

	/**
	 * An optional argument to define the output file path. The exporter will
	 * create results within that target file.
	 */
	public static class OutputToken extends StringToken
	{
		public OutputToken() {
			super("-output", StandaloneMessages.ValidateCommand_Output_Help);
		}
		
		public boolean check(@NonNull List<String> strings) {
			return getOutputFile(strings) != null;
		}

		public @Nullable String getArgsHelp() {
			return "<file-name>";
		}

		private @Nullable File getOutputFile(@NonNull List<String> strings) {
			if (strings.size() <= 0) {
				return null;
			}
			String string = strings.get(0);
			try {
				File file = new File(string).getCanonicalFile();
				if (file.exists()) {
					if (file.isFile()) {
						file.delete();
					} else {
						logger.error(StandaloneMessages.OCLArgumentAnalyzer_OutputFile
								+ file.getAbsolutePath()
								+ StandaloneMessages.OCLArgumentAnalyzer_NotFile);
					}
				}
				if (!file.exists()) {
//					outputFilePath = new Path(file.getAbsolutePath());
//					outputFile = file;
					File outputFolder = file.getParentFile();
					if (!outputFolder.exists()) {
						logger.error(StandaloneMessages.OCLArgumentAnalyzer_OutputDir
								+ outputFolder.getAbsolutePath()
								+ StandaloneMessages.OCLArgumentAnalyzer_NotExist);
					} else {
						return file;
					}
				}
			} catch (IOException e) {
				logger.error(e.getMessage());
			}
			return null;
		}

		public File getOutputFile(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			if (strings == null) {
				return null;
			}
			return getOutputFile(strings);
		}
	}


	/**
	 * A mandatory argument used to define the paths to the OCL documents
	 * containing the constraints to evaluate. Users can specify one or several
	 * OCL Documents paths in the command line, separated with a whitespace. A
	 * text file containing a list of OCL Documents paths can be used instead,
	 * in which case all OCL constraints defined in all of these documents will
	 * be evaluated sequentially.
	 */
	public static class RulesToken extends CommandToken
	{
		/** Possible "text" extension file for the "-rules" argument entry. */
		private static final Object TEXT_FILE_EXTENSION = "txt"; //$NON-NLS-1$
		/** Possible "ocl" extension file for the "-rules" argument entry. */
		private static final Object OCL_FILE_EXTENSION = "ocl"; //$NON-NLS-1$

		public RulesToken() {
			super("-rules", StandaloneMessages.ValidateCommand_Rules_Help);
		}

		public boolean check(@NonNull List<String> strings) {
			if (strings.size() <= 0) {
//				return false;			-- all files might be ignored
			}
			for (String string : strings) {
				String checkedName = getCheckedFileName(string);
				if (checkedName == null) {
					return false; 
				}
			}
			return true;
		}

		public int parseArgument(@NonNull List<String> strings, @NonNull String[] arguments, int i) {
			if (i < arguments.length){
				String argument = arguments[i++];
				checkOclFile(strings, argument);
				return i;
			}
			else {
				logger.error("No argument for '" + name + "'");
				return -1;
			}
		}

		/**
		 * Checks consistency of the ocl file passed to the command line.
		 * 
		 * @param argument
		 *            is the path to the relative/absolute path to the resource
		 * @return <code>true</code> if the model exists and is a file,
		 *         <code>false</code> otherwise.
		 */
		private void checkOclFile(@NonNull List<String> strings, @NonNull String argument) {
			if (argument.startsWith("file:")) {
				argument = argument.substring(5);
			}
			if (isWindows() && argument.startsWith("/")) {
				argument = argument.substring(1);
			}
			boolean ignored = false;
			try {
				File file = new File(argument).getCanonicalFile();
				IPath path = new Path(file.getCanonicalPath());
				// a txt file may contain relative or absolute path to a set of OCL
				// files.
				if (TEXT_FILE_EXTENSION.equals(path.getFileExtension().toLowerCase())) {
					extractOCLUris(strings, file);
				} else if (OCL_FILE_EXTENSION.equals(path.getFileExtension().toLowerCase())) {
					if (!file.exists()) {
						logger.warn(StandaloneMessages.OCLArgumentAnalyzer_OCLResource
								+ file.getAbsolutePath()
								+ StandaloneMessages.OCLArgumentAnalyzer_NotExist);
						ignored = true;
					} else if (!file.isFile()) {
						logger.warn(StandaloneMessages.OCLArgumentAnalyzer_OCLResource
								+ file.getAbsolutePath()
								+ StandaloneMessages.OCLArgumentAnalyzer_NotFile);
						ignored = true;
					} else if (!file.canRead()) {
						logger.warn(StandaloneMessages.OCLArgumentAnalyzer_OCLResource
								+ file.getAbsolutePath()
								+ StandaloneMessages.OCLArgumentAnalyzer_CannotBeRead);
						ignored = true;
					} else {
						strings.add(file.getAbsolutePath());
					}
				} else {
					logger.warn(StandaloneMessages.OCLArgumentAnalyzer_FileExt
							+ path.lastSegment()
							+ StandaloneMessages.OCLArgumentAnalyzer_ExtensionPb);
					ignored = true;
				}

				if (ignored) {
					logger.warn(StandaloneMessages.OCLArgumentAnalyzer_OCLFile
							+ file.getAbsolutePath()
							+ StandaloneMessages.OCLArgumentAnalyzer_ignored);

//				} else {
//					logger.info(StandaloneMessages.OCLArgumentAnalyzer_OCLFile
//							+ file.getAbsolutePath()
//							+ StandaloneMessages.OCLArgumentAnalyzer_found);
				}
			} catch (IOException e) {
				logger.warn(e.getMessage());
			}
		}

		/**
		 * Extracts information contained in the text file.
		 * 
		 * @param txtFile
		 *            The file containing relative path to OCL files.
		 */
		private void extractOCLUris(@NonNull List<String> strings, File txtFile) {
			BufferedReader reader;
			try {
				reader = new BufferedReader(new FileReader(txtFile));
				String line = reader.readLine();
				while (line != null) {
					File child = new File(txtFile.getParentFile(), line);
					checkOclFile(strings, child.toString());
					line = reader.readLine();
				}
				reader.close();
			} catch (FileNotFoundException e) {
				logger.error(MessageFormat
						.format(StandaloneMessages.OCLArgumentAnalyzer_OCLFileNotFound,
								txtFile.getAbsolutePath()));
			} catch (IOException e) {
				logger.warn(e.getMessage());
			}
		}

		public @Nullable String getArgsHelp() {
			return "<file-name>";
		}

		/**
		 * Gets the collection of OCL resources deduced from values specified after
		 * the <b>-rule</b> argument.
		 * 
		 * @return A List of OCL Uris
		 */
		public @NonNull List<String> getOCLFileNames(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			if (strings == null) {
				return Collections.emptyList();
			}
			return strings;
		}
	}


	/**
	 * An optional argument used if the user wishes to run all constraints or to
	 * only run the OCL, Java or UML constraints validation. Otherwise, all
	 * constraints will be checked against the input model.
	 */
	public static class UsingToken extends StringToken
	{
		/** "-using" argument value to run the all constraints (ocl, java and uml). */
		private static final String ALL_LOCATORS = "all"; //$NON-NLS-1$
		/** "-using" argument value to additionally run the OCL constraints. */
		private static final String OCL_LOCATOR = "ocl"; //$NON-NLS-1$
		/** "-using" argument value to additionally run the Java constraints. */
		private static final String JAVA_LOCATOR = "java"; //$NON-NLS-1$
		/** "-using" argument value to additionally run the UML constraints. */
		private static final String UML_LOCATOR = "uml"; //$NON-NLS-1$

		public UsingToken() {
			super("-using", StandaloneMessages.ValidateCommand_Using_Help);
		}
		
		public boolean check(@NonNull List<String> locators) {
			for (String locator : locators) {
				if (!ALL_LOCATORS.equals(locator) && !JAVA_LOCATOR.equals(locator) && !OCL_LOCATOR.equals(locator) && !UML_LOCATOR.equals(locator)) {
					logger.error("Unknown locator '" + locator + "'");
					return false;
				}
			}
			return true;
		}

		public boolean doRunJavaConstraints(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			return (strings == null) || strings.contains(JAVA_LOCATOR) || strings.contains(ALL_LOCATORS);
		}

		public boolean doRunOCLConstraints(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			return (strings == null) || strings.contains(OCL_LOCATOR) || strings.contains(ALL_LOCATORS);
		}

		public boolean doRunUMLConstraints(@NonNull Map<CommandToken, List<String>> token2strings) {
			List<String> strings = token2strings.get(this);
			return (strings == null) || strings.contains(UML_LOCATOR) || strings.contains(ALL_LOCATORS);
		}

		public @Nullable String getArgsHelp() {
			return ALL_LOCATORS + "|" + JAVA_LOCATOR + "|" + OCL_LOCATOR + "|" + UML_LOCATOR;
		}

		@Override
		public boolean isSingleton() {
			return false;
		}

		@Override
		public int parseArgument(@NonNull List<String> strings, @NonNull String[] arguments, int i) {
			if (i < arguments.length){
				String argument = arguments[i++];
				String[] locators = argument.split(",");
				for (String locator : locators) {
					if (!ALL_LOCATORS.equals(locator) && !JAVA_LOCATOR.equals(locator) && !OCL_LOCATOR.equals(locator) && !UML_LOCATOR.equals(locator)) {
						logger.error("Unknown locator '" + locator + "'");
						return -1;
					}
				}
				for (String locator : locators) {
					strings.add(locator);
				}
				return i;
			}
			else {
				logger.error("No argument for '" + name + "'");
				return -1;
			}
		}
	}

	protected static String getCheckedFileName(@NonNull String string) {
		if (string.startsWith("file:")) {
			string = string.substring(5);
		}
		if (isWindows() && string.startsWith("/")) {
			string = string.substring(1);
		}
		try {
			File file = new File(string).getCanonicalFile();
			if (!file.exists()) {
				logger.error(StandaloneMessages.OCLArgumentAnalyzer_ModelFile
						+ file.getAbsolutePath()
						+ StandaloneMessages.OCLArgumentAnalyzer_NotExist);
			} else if (!file.isFile()) {
				logger.error(StandaloneMessages.OCLArgumentAnalyzer_ModelFile
						+ file.getAbsolutePath()
						+ StandaloneMessages.OCLArgumentAnalyzer_NotFile);
			} else {
				@SuppressWarnings("unused")
				IPath modelPath = new Path(file.getAbsolutePath());
//				logger.info(StandaloneMessages.OCLArgumentAnalyzer_ModelFile
//						+ file.getAbsolutePath()
//						+ StandaloneMessages.OCLArgumentAnalyzer_found);
				return string;//modelPath;
			}
		} catch (IOException e) {
			logger.error(e.getMessage());
		}
		return null;
	}

	/**
	 * Gets an URI from a file Path.
	 * 
	 * @param filePath
	 *            the file path.
	 * @return an URI from the path.
	 */
	private static URI getFileUri(@NonNull String fileName) {
		final URI fileUri;
		File file;
		try {
			file = new File(fileName).getCanonicalFile();		// FIXME is this necessary
			IPath filePath = new Path(file.getAbsolutePath());
//			IPath filePath = new Path(fileName);
			if (isRelativePath(filePath)) {
				fileUri = URI.createPlatformResourceURI(filePath.toString(), true);
			} else {
				fileUri = URI.createFileURI(filePath.toString());
			}
			return fileUri;
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * Checks if the path is relative or absolute.
	 * 
	 * @param path
	 *            a file path.
	 * @return true if the path is relative, false otherwise.
	 */
	private static boolean isRelativePath(IPath path) {
		try {
			IResource resource = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
			return resource != null && resource.exists();
		} catch (IllegalStateException exception) {
			return false;
		}
	}

	public static boolean isWindows() {
		String os = System.getProperty("os.name");
		return (os != null) && os.startsWith("Windows");
	}

	public final @NonNull ExporterToken exporterToken = new ExporterToken();
	public final @NonNull ModelToken modelToken = new ModelToken();
	public final @NonNull OutputToken outputToken = new OutputToken();
	public final @NonNull RulesToken rulesToken = new RulesToken();
	public final @NonNull UsingToken usingToken = new UsingToken();

	public ValidateCommand(@NonNull StandaloneApplication standaloneApplication) {
		super(standaloneApplication, "validate", StandaloneMessages.ValidateCommand_Help);
		modelToken.setIsRequired();
		rulesToken.setIsRequired();
		addToken(modelToken);
		addToken(rulesToken);
		addToken(outputToken);
		addToken(exporterToken);
		addToken(usingToken);
	}
	
	public @NonNull StandaloneResponse execute(@NonNull Map<CommandToken, List<String>> token2strings) {
		standaloneApplication.doCompleteOCLSetup();
		String modelFileName = modelToken.getModelFileName(token2strings);
		List<String> oclFileNames = rulesToken.getOCLFileNames(token2strings);
		URI modelURI = getFileUri(modelFileName);
		// Load model resource
		Resource modelResource = standaloneApplication.loadModelFile(modelURI);
		if (modelResource == null) {
			logger.error(MessageFormat.format(StandaloneMessages.OCLValidatorApplication_ModelLoadProblem, modelFileName));
			return StandaloneResponse.FAIL;
		}
		if (!processResources(modelFileName, oclFileNames)) {
			logger.error(StandaloneMessages.OCLValidatorApplication_Aborted);
			return StandaloneResponse.FAIL;
		}
		if (ValidationAdapter.findAdapter(standaloneApplication.getResourceSet()) == null) {
			logger.error(StandaloneMessages.OCLValidatorApplication_Aborted);
			return StandaloneResponse.FAIL;
		}
		StandaloneValidityManager validityManager = initiateValidityManager(standaloneApplication.getResourceSet(), token2strings);
		
		if (validityManager != null) {
			// run the validation
			validate(validityManager);

			// export results
			File outputFile = outputToken.getOutputFile(token2strings);
			exportValidationResults(validityManager.getRootNode(), modelResource, outputFile, token2strings);
//			try {
//				exportValidationResults(getOutputWriter(), validityManager.getRootNode());
//			} catch (IOException e) {
//				// TODO Auto-generated catch block
//				e.printStackTrace();
//			}
		}
		return StandaloneResponse.OK;
	}

	/**
	 * Exports Validation results.
	 * 
	 * @param rootNode
	 *            the validity model rootNode.
	 * @param outputPath
	 *            the exported file path.
	 */
	private void exportValidationResults(@NonNull RootNode rootNode, @NonNull Resource modelResource, @Nullable File outputFile, @NonNull Map<CommandToken, List<String>> token2strings) {
		final IValidityExporter selectedExporter = exporterToken.getExporter(token2strings);
		if (selectedExporter != null && modelResource != null && rootNode != null) {
//			logger.info(StandaloneMessages.OCLValidatorApplication_ExportStarting);
			Appendable s = null;
			try {
				s = outputFile != null ? new FileWriter(outputFile) : System.out;
				selectedExporter.export(s, modelResource, rootNode, outputFile != null ? outputFile.toString() : null);
			} catch (IOException e) {
				logger.error(StandaloneMessages.OCLValidatorApplication_ExportProblem, e);
			} finally {
				if (s != System.out) {
					try {
						((FileWriter)s).close();
					} catch (IOException e) {}
				}
			}
//			logger.info(StandaloneMessages.OCLValidatorApplication_ExportedFileGenerated);
//		} else {
//			logger.info(StandaloneMessages.OCLValidatorApplication_ExportProblem);
		}
	}

	/**
	 * Initiates the validity manager using the resourceSet.
	 * 
	 * @param resourceSet
	 *            the resource set.
	 */
	private @NonNull StandaloneValidityManager initiateValidityManager(@NonNull ResourceSet resourceSet, @NonNull Map<CommandToken, List<String>> token2strings) {
		StandaloneValidityManager validityManager = new StandaloneValidityManager();
		validityManager.setRunJavaConstraints(usingToken.doRunJavaConstraints(token2strings));
		validityManager.setRunOCLConstraints(usingToken.doRunOCLConstraints(token2strings));
		validityManager.setRunUMLConstraints(usingToken.doRunUMLConstraints(token2strings));
		validityManager.setInput(resourceSet);
		return validityManager;
	}

	/**
	 * Loads the entered model and ocl files.
	 * 
	 * @param modelFilePath
	 *            the model to validate file path.
	 * @param oclPaths
	 *            the ocl files paths.
	 * @return true if there is not problem while loading, false otherwise.
	 */
	private boolean processResources(@NonNull String modelFilePath, @NonNull List<String> oclFileNames) {
		boolean allOk = true;

		Helper helper = new Helper(standaloneApplication.getResourceSet()) {
			@Override
			protected boolean error(@NonNull String primaryMessage, @Nullable String detailMessage) {
				logger.error(primaryMessage + detailMessage);
				return false;
			}
		};

		for (String oclFileName : oclFileNames) {
			URI oclURI = getFileUri(oclFileName);

			if (allOk && oclURI == null) {
				logger.error(MessageFormat.format(StandaloneMessages.OCLValidatorApplication_OclUriProblem, oclFileName));
				allOk = false;
			}

			// Load ocl models
//			if (done && standaloneApplication.loadModelFile(oclURI) == null) {
//				logger.error(MessageFormat.format(StandaloneMessages.OCLValidatorApplication_OclLoadProblem, oclFileName));
//				done = false;
//			}

			// Load as ocl documents
			try {
				if (allOk) {
					Resource oclResource = helper.loadResource(oclURI);
					if (oclResource == null) {
						logger.error(MessageFormat.format(StandaloneMessages.OCLValidatorApplication_OclLoadProblem, oclFileName));
						allOk = false;
					}
				}
			} catch (Throwable e) {
				logger.error(MessageFormat.format(StandaloneMessages.OCLValidatorApplication_OclLoadProblem, oclFileName));
				allOk = false;
			}
		}

		if (allOk && !helper.loadMetaModels()) {
			logger.error(StandaloneMessages.OCLValidatorApplication_MetaModelsLoadProblem);
			allOk = false;
		}

		helper.installPackages();
		return allOk;
	}

	/**
	 * Runs the validation
	 */
	private void validate(@NonNull StandaloneValidityManager validityManager) {
//		logger.info(StandaloneMessages.OCLValidatorApplication_ValidationStarting);
		validityManager.runValidation();
//		logger.info(StandaloneMessages.OCLValidatorApplication_ValidationComplete);
	}
}
