/*******************************************************************************
 * Copyright (c) 2008, 2011 Mia-Software.
 * 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:
 *    Gabriel Barbier (Mia-Software) - initial API and implementation
 *    Fabien Giquel (Mia-Software)
 *    Nicolas Bros (Mia-Software)
 *******************************************************************************/

package org.eclipse.gmt.modisco.infra.common.core.internal.utils;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.util.Comparator;
import java.util.Enumeration;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.gmt.modisco.infra.common.core.internal.CommonModiscoActivator;
import org.eclipse.gmt.modisco.infra.common.core.logging.MoDiscoLogger;
import org.osgi.framework.Bundle;

/** @author Gabriel Barbier */
public final class FolderUtils {
	private static final int COPY_BUFFER_SIZE = 512 * 1024;

	private static boolean debug = false;

	private static FolderUtils.ConfigurationManagementFilter configurationManagementFilter;

	private static class ConfigurationManagementFilter implements FilenameFilter {
		private static final String FILTER_NAME = "CVS"; //$NON-NLS-1$

		/**
		 * Tests if a specified file should be included in a file list.
		 *
		 *
		 * @param dir
		 *            the directory in which the file was found.
		 * @param name
		 *            the name of the file.
		 *
		 * @return <code>true</code> if and only if the name should be included
		 *         in the file list; <code>false</code> otherwise.
		 */
		public boolean accept(final File dir, final String name) {
			boolean result = false;
			if (!name.equals(FolderUtils.ConfigurationManagementFilter.FILTER_NAME)) {
				result = true;
			}
			return result;
		}
	}

	private FolderUtils() {
		// prevent instantiation
	}

	public static final void clearFolder(final File dirtyFolder) {
		assert dirtyFolder != null;
		assert dirtyFolder.exists();
		assert dirtyFolder.isDirectory();
		/*
		 * To delete the contents of this folder, we recurse on all elements
		 * (File) in this folder. In the case of a directory, we first delete
		 * its own contents before deleting it. In the case of a file, we just
		 * delete the file.
		 */
		File[] files = dirtyFolder.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				FolderUtils.clearFolder(file);
			}
			file.delete();
		}
	}

	/**
	 * This method compares two folders (in fact the contents of these two
	 * folders). It is recursive into each folder
	 */
	public static final boolean compareFolders(final File folderSource, final File folderTarget) {
		return FolderUtils.compareFolders(folderSource, folderTarget,
				FolderUtils.configurationManagementFilter, FolderUtils.getDefaultFileComparator());
	}

	public static final boolean compareFolders(final File folderSource, final File folderTarget,
			final FilenameFilter filter) {
		return FolderUtils.compareFolders(folderSource, folderTarget, filter,
				FolderUtils.getDefaultFileComparator());
	}

	public static final boolean compareFolders(final File folderSource, final File folderTarget,
			final FilenameFilter filter, final Comparator<File> fileComparison) {
		assert ((folderSource != null) && (folderTarget != null));
		assert ((folderSource.isDirectory()) && (folderTarget.isDirectory()));
		boolean result = false;
		if (folderSource.equals(folderTarget)) {
			result = true;
		} else {
			result = FolderUtils.recursiveCompareFolders(folderSource, folderTarget, filter,
					fileComparison);
			if (FolderUtils.debug && !result) {
				MoDiscoLogger
						.logError(
								"folders " + folderSource.getName() + " and " + folderTarget.getName() + " are not equal.", CommonModiscoActivator.getDefault()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}
		}
		return result;
	}

	public static final boolean compareFiles(final File source, final File target) {
		return FolderUtils.compareFiles(source, target, FolderUtils.getDefaultFileComparator());
	}

	private static final Comparator<File> getDefaultFileComparator() {
		return new Comparator<File>() {
			public int compare(final File source, final File target) {
				boolean result = true;
				if (!source.getName().equals(target.getName())) {
					result = false;
				} else {
					// Compare file line by line
					BufferedReader sourceReader = null;
					BufferedReader targetReader = null;
					try {
						sourceReader = new BufferedReader(new FileReader(source));
						targetReader = new BufferedReader(new FileReader(target));
						String sourceLine = sourceReader.readLine();
						String targetLine = targetReader.readLine();
						while ((sourceLine != null) && (targetLine != null)) {
							result = result && sourceLine.equals(targetLine);
							sourceLine = sourceReader.readLine();
							targetLine = targetReader.readLine();
						}
						if ((sourceLine != null) || (targetLine != null)) {
							result = false;
							MoDiscoLogger
									.logError(
											"These files do not have the same number of lines.", CommonModiscoActivator.getDefault()); //$NON-NLS-1$
						}
					} catch (FileNotFoundException e) {
						result = false;
					} catch (IOException e) {
						result = false;
					} finally {
						if (sourceReader != null) {
							try {
								sourceReader.close();
							} catch (IOException e) {
								MoDiscoLogger.logError(e, CommonModiscoActivator.getDefault());
							}
						}
						if (targetReader != null) {
							try {
								targetReader.close();
							} catch (IOException e) {
								MoDiscoLogger.logError(e, CommonModiscoActivator.getDefault());
							}
						}
					}
				}
				if (result) {
					return 0;
				}
				return -1;
			}
		};
	}

	public static final boolean compareFiles(final File source, final File target,
			final Comparator<File> fileComparator) {
		assert ((source.isFile()) && (target.isFile()));
		boolean result = (fileComparator.compare(source, target) == 0);
		if (FolderUtils.debug && result) {
			MoDiscoLogger
					.logInfo(
							"Files " + source.getName() + " and " + target.getName() + " are equal.", CommonModiscoActivator.getDefault()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}
		return result;
	}

	public static final String getFileContent(final File source) {
		StringBuilder result = new StringBuilder();
		BufferedReader sourceReader = null;
		try {
			sourceReader = new BufferedReader(new FileReader(source));
			String sourceLine = sourceReader.readLine();
			while (sourceLine != null) {
				result.append(sourceLine);
				result.append("\n"); //$NON-NLS-1$
				sourceLine = sourceReader.readLine();
			}
		} catch (FileNotFoundException e) {
			MoDiscoLogger.logError(e, CommonModiscoActivator.getDefault());
		} catch (IOException e) {
			MoDiscoLogger.logError(e, CommonModiscoActivator.getDefault());
		} finally {
			if (sourceReader != null) {
				try {
					sourceReader.close();
				} catch (IOException e) {
					MoDiscoLogger.logError(e, CommonModiscoActivator.getDefault());
				}
			}
		}
		return result.toString();
	}

	/**
	 * This method compares two folders (in fact the contents of these two
	 * folders). It is recursive into each folder
	 */
	private static final boolean recursiveCompareFolders(final File folderSource,
			final File folderTarget, final FilenameFilter filter,
			final Comparator<File> fileComparison) {
		if (FolderUtils.debug) {
			MoDiscoLogger
					.logError(
							"comparison of " + folderSource.getName() + " and " + folderTarget.getName(), CommonModiscoActivator.getDefault()); //$NON-NLS-1$ //$NON-NLS-2$
		}
		boolean result = true;

		File[] sourceContents = folderSource.listFiles(filter);
		File[] targetContents = folderTarget.listFiles(filter);
		if (sourceContents.length != targetContents.length) {
			result = false;
			if (FolderUtils.debug) {
				MoDiscoLogger.logError("folders " + folderSource.getName() + " and " //$NON-NLS-1$//$NON-NLS-2$
						+ folderTarget.getName() + " do not have the same number of children (" //$NON-NLS-1$
						+ sourceContents.length + ", " + targetContents.length + ")", //$NON-NLS-1$ //$NON-NLS-2$
						CommonModiscoActivator.getDefault());
			}
		} else {
			for (File sourceContent : sourceContents) {
				/*
				 * For each File in the current directory, we test if it has a
				 * counterpart in the contents of the target directory. The
				 * search is based on the path name, so there can be problems if
				 * a file has the same name as a directory.
				 */
				File targetContent = FolderUtils.getCorrespondingTargetContent(sourceContent,
						targetContents);
				if (targetContent == null) {
					result = false;
					if (FolderUtils.debug) {
						MoDiscoLogger
								.logError(
										"There is no corresponding element in target folder for " + sourceContent.getName(), CommonModiscoActivator.getDefault()); //$NON-NLS-1$
					}
				} else {
					/*
					 * Two cases: for a directory, recurse into its contents,
					 * and for a file, compare the contents of the two files.
					 */
					if (sourceContent.isDirectory()) {
						boolean subResult = FolderUtils.recursiveCompareFolders(sourceContent,
								targetContent, filter, fileComparison);
						result = result && subResult;

						if (FolderUtils.debug && !subResult) {
							MoDiscoLogger
									.logError(
											"folders " + sourceContent.getName() + " and " + targetContent.getName() + " are not equal.", CommonModiscoActivator.getDefault()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}
					} else {
						boolean subResult = FolderUtils.compareFiles(sourceContent, targetContent,
								fileComparison);
						result = result && subResult;
						if (FolderUtils.debug && !subResult) {
							MoDiscoLogger
									.logError(
											"files " + sourceContent.getName() + " and " + targetContent.getName() + " are not equal.", CommonModiscoActivator.getDefault()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						}
					}
				}
			}
		}
		return result;
	}

	private static final File getCorrespondingTargetContent(final File sourceContent,
			final File[] targetContents) {
		File targetContent = null;
		for (File temp : targetContents) {
			if (sourceContent.getName().equals(temp.getName())) {
				targetContent = temp;
			}
		}
		return targetContent;
	}

	/**
	 * Copies the source directory to the target directory. The target is
	 * created if it does not exist.
	 */
	public static final void copyDirectory(final File srcDir, final File destDir)
			throws IOException {
		FolderUtils.copyDirectory(srcDir, destDir, new IFilter() {
			public boolean filter(final Object object) {
				return true;
			}
		});
	}

	public static final void copyDirectory(final File srcDir, final File destDir,
			final IFilter filter) throws IOException {

		if (!destDir.exists()) {
			destDir.mkdirs();
		}
		File[] filesList = srcDir.listFiles();
		File dest;
		// Copies each file and directory, one by one
		for (File src : filesList) {
			dest = new File(destDir.getPath() + File.separator + src.getName());
			if (filter.filter(dest)) {
				if (src.isDirectory()) {
					FolderUtils.copyDirectory(src, dest, filter);
				} else {
					FolderUtils.copyFile(src, dest);
				}
			}
		}

	}

	public static void copyFolderFromBundle(final String sourcePath, final Plugin sourcePlugin,
			final String destinationPath, final IProject project) throws IOException, CoreException {
		FolderUtils.copyFolderFromBundle(sourcePath, sourcePlugin.getBundle(), destinationPath,
				project);
	}

	/**
	 * Copies the source directory to the target directory. The target is
	 * created if it does not exist.
	 */
	public static void copyFolderFromBundle(final String sourcePath, final Bundle sourceBundle,
			final String destinationPath, final IProject project) throws IOException, CoreException {
		Enumeration<?> e = sourceBundle.getEntryPaths(sourcePath);
		if (e == null) {
			// it should be a file (not a folder)
			try {
				InputStream source = sourceBundle.getEntry(sourcePath).openStream();
				IFile javaFile = project.getFile(destinationPath);
				if (javaFile.exists()) {
					javaFile.delete(true, new NullProgressMonitor());
				}
				javaFile.create(source, true, new NullProgressMonitor());
			} catch (Exception e1) {
				MoDiscoLogger.logError(e1, CommonModiscoActivator.getDefault());
			}
		} else {
			String subDestinationPath = "/"; //$NON-NLS-1$
			if (!destinationPath.equals("/")) { //$NON-NLS-1$
				IFolder folder = project.getFolder(destinationPath);
				if (!folder.exists()) {
					try {
						folder.create(true, true, new NullProgressMonitor());
					} catch (Exception e1) {
						MoDiscoLogger.logError(e1, CommonModiscoActivator.getDefault());
					}
				}
				subDestinationPath = folder.getProjectRelativePath().toString();
			}
			while (e.hasMoreElements()) {
				Object object = e.nextElement();
				if (object instanceof String) {
					String subpath = (String) object;
					if (!subpath.matches(".*/\\.svn/")) { //$NON-NLS-1$
						String dest = subDestinationPath
								+ subpath.substring(sourcePath.length() - 1);
						FolderUtils.copyFolderFromBundle(subpath, sourceBundle, dest, project);
					}
				} else {
					throw new RuntimeException("Unexpected element type"); //$NON-NLS-1$
				}
			}
		}
	}

	/**
	 * Copies the source file to the target file.
	 *
	 * @return <code>true</code> if successful, <code>false</code> otherwise
	 */
	public static final boolean copyFile(final File source, final File destination) {
		boolean result = false;
		FileInputStream sourceFile = null;
		FileOutputStream destinationFile = null;
		try {
			// File creation
			destination.createNewFile();
			sourceFile = new FileInputStream(source);
			destinationFile = new FileOutputStream(destination);
			// 0.5 MiB buffer for reading
			byte[] buffer = new byte[FolderUtils.COPY_BUFFER_SIZE];
			int nbRead;
			while ((nbRead = sourceFile.read(buffer)) != -1) {
				destinationFile.write(buffer, 0, nbRead);
			}

			// Copied
			result = true;
		} catch (java.io.FileNotFoundException f) {
			result = false;
		} catch (java.io.IOException e) {
			result = false;
		} finally {
			try {
				if (sourceFile != null) {
					sourceFile.close();
				}
				if (destinationFile != null) {
					destinationFile.close();
				}
			} catch (Exception e) {
				result = false;
			}
		}
		return result;
	}

	/**
	 * Recursively delete a directory.
	 *
	 * @param directory
	 *            directory to delete
	 * @throws IOException
	 *             in case deletion is unsuccessful
	 */
	public static final void deleteDirectory(final File directory) throws IOException {
		if (!directory.exists()) {
			return;
		}

		FolderUtils.clearFolder(directory);
		if (directory.list().length == 0) {
			// delete directory
			if (!directory.delete()) {
				String message = "Unable to delete directory " + directory + "."; //$NON-NLS-1$ //$NON-NLS-2$
				throw new IOException(message);
			}
		}
	}

	public static void createFolder(final IFolder folder) throws CoreException {
		if (!folder.getParent().exists()) {
			FolderUtils.createFolder((IFolder) folder.getParent());
		}
		if (!folder.exists()) {
			folder.create(true, true, new NullProgressMonitor());
		}
	}

	/**
	 * write a new content into a given file.
	 *
	 * @param source
	 *            source file. It will be created if it does not exist.
	 * @param newContent
	 * @throws IOException
	 */
	public static final void writeFileContent(final File source, final String newContent)
			throws IOException {
		FileWriter fw = new FileWriter(source, false);
		fw.write(newContent);
		fw.close();
	}
}
