/*******************************************************************************
 * Copyright (c) 2008 The University of York.
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 * 
 * Contributors:
 *     Dimitrios Kolovos - initial API and implementation
 ******************************************************************************/
package org.eclipse.epsilon.common.util;

import static java.nio.file.attribute.PosixFilePermission.OWNER_EXECUTE;
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
import static java.security.AccessController.doPrivileged;

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.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.nio.channels.FileChannel;
import java.nio.file.DirectoryStream;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.attribute.PosixFilePermissions;
import java.util.*;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FileUtil {

	private static Logger logger = LoggerFactory.getLogger(FileUtil.class);
	// temporary directory location
	private static final Path tmpdir = Paths.get(System.getProperty("java.io.tmpdir"));

	private static final boolean isPosix = FileSystems.getDefault().supportedFileAttributeViews().contains("posix");

	// default file and directory permissions (lazily initialized)
	private static class PosixPermissions {
		static final FileAttribute<Set<PosixFilePermission>> filePermissions = PosixFilePermissions
				.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE));
		static final FileAttribute<Set<PosixFilePermission>> dirPermissions = PosixFilePermissions
				.asFileAttribute(EnumSet.of(OWNER_READ, OWNER_WRITE, OWNER_EXECUTE));
	}

	private FileUtil() {
	}

	public static Path getCurrentDirectory() {
		return Paths.get(".").toAbsolutePath().normalize();
	}

	public static void setFileContents(String str, File file) throws Exception {
		try (FileWriter writer = new FileWriter(file)) {
			writer.append(str);
			writer.flush();
		}
	}

	public static String replaceExtension(String filename, String newExtension) {
		int dotIndex = filename.lastIndexOf('.');
		if (dotIndex > -1) {
			filename = filename.substring(0, dotIndex + 1) + newExtension;
		}
		return filename;
	}

	public static String removeExtension(String filename) {
		int dotIndex = filename.lastIndexOf('.');
		if (dotIndex > -1) {
			filename = filename.substring(0, dotIndex);
		}
		return filename;
	}

	public static String getFileName(String path) {
		return getFileName(path, true);
	}

	public static String getFileName(String path, boolean includeExtension) {
		String filename = path.substring(path.replace("\\", "/").lastIndexOf('/') + 1);
		if (!includeExtension) {
			filename = removeExtension(filename);
		}
		return filename;
	}

	/**
	 * Copied from @linkplain{https://stackoverflow.com/a/3571239/5870336}
	 * 
	 * @param filename
	 * @return
	 * @since 1.6
	 */
	public static String getExtension(String filename) {
		String extension = "";
		int dotIndex = filename.lastIndexOf('.');
		if (dotIndex > Math.max(filename.lastIndexOf('/'), filename.lastIndexOf('\\'))) {
			extension = filename.substring(dotIndex + 1);
		}
		return extension;
	}

	public static String getFileContents(File file) throws Exception {
		final StringBuffer buffer = new StringBuffer();
		final String lineSeparator = System.getProperty("line.separator");

		for (String line : getFileLineContents(file)) {
			buffer.append(line);
			buffer.append(lineSeparator);
		}

		return buffer.toString();
	}

	public static Collection<String> getFileLineContents(File file) throws Exception {
		try (BufferedReader bufferedReader = new BufferedReader(new FileReader(file))) {
			final List<String> lines = new LinkedList<>();

			String line = bufferedReader.readLine();

			while (line != null) {
				lines.add(line);
				line = bufferedReader.readLine();
			}

			return lines;
		}
	}

	public static String getAbsolutePath(String basePath, String relativePath) {
		File file = new File(relativePath);
		if (!file.isAbsolute()) {
			file = new File(basePath, relativePath);
		}
		return file.getAbsolutePath();
	}

	/**
	 * Gets a file stored as a resource in a jar. Since not all users of the file
	 * can read from inside jars, we get the file as a stream and create a temp file
	 * with its contents.
	 * 
	 * @param name
	 * @param relativeTo
	 * @return
	 */
	public static File getFile(String name, Class<?> relativeTo) {
		logger.info("getFile {}@{}", name, relativeTo.getSimpleName());
		InputStream is = relativeTo.getResourceAsStream(name);
		return inputStreamToFile(is, name);
	}

	@Deprecated
	public static File getDirectoryOf(Class<?> clazz) {
		return getFile(clazz.getSimpleName() + ".class", clazz).getParentFile();
	}

	@Deprecated
	public static String getPath(String name, Class<?> relativeTo) {
		return getFile(name, relativeTo).getAbsolutePath();
	}

	public static void checkFileExists(final File file) throws FileNotFoundException {
		if (!file.exists()) {
			throw new FileNotFoundException("File " + file.getPath() + " does not exist");
		}
	}

	public static File createTempFile(String name) {
		return createTempFile(name, "tmp");
	}

	public static File createTempFile(String name, String extension) {
		Path tmpFile;
		try {
			// tmpFile = Files.createTempFile(name, extension);
			tmpFile = createTempFile(null, name, extension);
		} catch (IOException e) {
			throw new IllegalArgumentException("Could not create temp file ", e);
		}
		return tmpFile.toFile();
	}

	public static File createTempDir(String name) {
		return createTempDir(name, false);
	}

	public static File createTempDir(String name, boolean reuse) {
		Path tmpFile = null;
		if (reuse) {
			DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
				@Override
				public boolean accept(Path file) throws IOException {
					return (Files.isDirectory(file) && file.getFileName().startsWith(Paths.get(name)));
				}
			};
			Iterator<Path> it;
			try {
				it = Files.newDirectoryStream(tmpdir, filter).iterator();
				tmpFile = it.hasNext() ? it.next() : null;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		if (tmpFile == null) {
			try {
				tmpFile = createTempDirectory(null, name);
			} catch (IOException e) {
				throw new IllegalArgumentException("Could not create temp directory ", e);
			}
		}
		return tmpFile.toFile();
	}

	public static File copyToTemp(File srcFile) throws IOException {
		File tmpFile = File.createTempFile("filecompare", "tmp");
		if (srcFile.isDirectory()) {
			tmpFile.delete();
			tmpFile.mkdir();
		}
		copy(srcFile, tmpFile);
		return tmpFile;
	}

	public static void copy(File srcFile, File dstFile) throws IOException {
		if (srcFile.isDirectory()) {
			dstFile.mkdir();
			for (File entry : srcFile.listFiles()) {
				copy(entry, new File(dstFile, entry.getName()));
			}
		} else {
			// Based on the second answer in http://stackoverflow.com/questions/106770.
			FileInputStream isSrc = null;
			FileOutputStream osDst = null;
			FileChannel chSrc = null;
			FileChannel chDst = null;
			try {
				isSrc = new FileInputStream(srcFile);
				osDst = new FileOutputStream(dstFile);
				chSrc = isSrc.getChannel();
				chDst = osDst.getChannel();
				final long srcBytes = srcFile.length();
				long transferred = 0;
				while (transferred < srcBytes) {
					transferred += chDst.transferFrom(chSrc, transferred, srcBytes);
					chDst.position(transferred);
				}
			} finally {
				if (chDst != null) {
					chDst.close();
				} else if (osDst != null) {
					osDst.close();
				}

				if (chSrc != null) {
					chSrc.close();
				} else if (isSrc != null) {
					isSrc.close();
				}
			}
		}
	}

	public static Set<String> listFilesAsSet(File fileExpected) {
		return new HashSet<>(Arrays.asList(fileExpected.list()));
	}

	/**
	 * We implement our own comparison algorithm here, so we don't need Eclipse
	 * Compare to compute differences, but rather only to show them in the UI.
	 */
	public static boolean sameContents(File fileExpected, File fileActual, Set<String> ignoreFilenames)
			throws IOException {
		if (fileExpected.isDirectory() != fileActual.isDirectory()) {
			// One is a file, the other is a directory: not the same
			return false;
		}

		if (fileExpected.isDirectory()) {
			// Both are directories: they should contain the same filenames,
			// and each pair should have the same contents
			final Set<String> expectedFilenames = listFilesAsSet(fileExpected);
			final Set<String> actualFilenames = listFilesAsSet(fileActual);
			expectedFilenames.removeAll(ignoreFilenames);
			actualFilenames.removeAll(ignoreFilenames);

			if (!expectedFilenames.equals(actualFilenames)) {
				return false;
			}
			for (String filename : expectedFilenames) {
				final File expectedEntry = new File(fileExpected, filename);
				final File actualEntry = new File(fileActual, filename);
				if (!sameContents(expectedEntry, actualEntry, ignoreFilenames)) {
					return false;
				}
			}
			return true;
		} else {
			if (fileExpected.length() != fileActual.length()) {
				// Different length: no need to read the files
				return false;
			}

			try (FileInputStream isExpected = new FileInputStream(fileExpected)) {
				try (FileInputStream isActual = new FileInputStream(fileActual)) {
					return sameContents(isExpected, isActual);
				}
			}
		}
	}

	public static boolean sameContents(InputStream isExpected, InputStream isActual) throws IOException {
		int chExpected, chActual;

		do {
			chExpected = isExpected.read();
			chActual = isActual.read();
		} while (chExpected == chActual && chExpected > 0 && chActual > 0);

		return chExpected == chActual;
	}

	/**
	 * WARNIING: Use with caution! Deletes all contents and sub-directories of the
	 * specified path.
	 * 
	 * @param dir The absolute path to the directory.
	 * @throws IOException
	 * @since 1.6
	 */
	public static void deleteDirectory(String dir) throws IOException {
		Path path = Paths.get(dir);
		if (Files.exists(path)) {
			Files.walk(path).map(Path::toFile).sorted((o1, o2) -> -o1.compareTo(o2)).forEach(File::delete);
		}
	}

	/**
	 * Reads entire directory recursively, mapping the contents of each file as a
	 * string to its path.
	 * 
	 * @param dir The root directory.
	 * @return The contents of each file in the directory and its subdirectories.
	 * @throws IOException
	 * @since 1.6
	 */
	public static Map<Path, String> readDirectory(String dir) throws IOException {
		Map<Path, String> contents = new HashMap<>();

		for (Path path : ((Iterable<Path>) Files.walk(Paths.get(dir))::iterator)) {
			if (Files.isRegularFile(path)) {
				contents.put(path, new String(Files.readAllBytes(path)));
			}
		}

		return contents;
	}

	private static File inputStreamToFile(InputStream inputStream, String name) {
		logger.debug("inputStreamToFile {}", name);
		OutputStream outputStream = null;
		String prefix = name;
		String suffix = "";
		Path dirStructure = null;
		
		// Name might be a path, get the file name, remove it
		if (name.contains("/")) {
			dirStructure = Paths.get(tmpdir.toString(), name.substring(0, name.lastIndexOf("/")), "/");
			dirStructure.toFile().mkdirs();
			name = name.substring(name.lastIndexOf("/") + 1);
			logger.debug("inputStreamToFile {}", name);
		}

		String[] parts = name.split("\\.");
		if (parts.length == 2) {
			prefix = parts[0];
			suffix = "." + parts[1];
			logger.debug("splitting name and extension: {} - {}", prefix, suffix);
		}
		File file = null;
		try {
			Path tempFile;
			try {
				// tempFile = Files.createTempFile(prefix, sufix);
				tempFile = createTempFile(dirStructure, prefix, suffix);
			} catch (IllegalArgumentException e) {
				logger.error("Error creating temp file: {}-{}", prefix, suffix, e);
				throw e;
			}
			outputStream = new FileOutputStream(tempFile.toFile());

			int read = 0;
			byte[] bytes = new byte[1024];
			logger.debug("{} bytes available", inputStream.available());
			while ((read = inputStream.read(bytes)) != -1) {
				logger.debug("{} bytes read from input", read);
				outputStream.write(bytes, 0, read);
			}
			logger.debug("Copying data into temp file Done!");
//			Runtime.getRuntime().addShutdownHook(new Thread() {
//	            @Override
//	            public void run() {
//	                try {
//	                    Files.delete(tempFile);
//	                } catch (IOException e) {
//	                    e.printStackTrace();
//	                }
//	            }
//	        });
			file = tempFile.toFile();

		} catch (IOException e) {
			logger.error("Unable to create File for resoruce", e);
			e.printStackTrace();
		} finally {
			if (inputStream != null) {
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}

			}
		}

		return file;
	}

	static Path createTempDirectory(Path dir, String prefix, FileAttribute<?>... attrs) throws IOException {
		return create(dir, prefix, null, true, attrs);
	}

	static Path createTempFile(Path dir, String prefix, String suffix, FileAttribute<?>... attrs) throws IOException {
		return create(dir, prefix, suffix, false, attrs);
	}

	/**
	 * Creates a file or directory in in the given given directory (or in the
	 * temporary directory if dir is {@code null}).
	 */
	private static Path create(Path dir, String prefix, String suffix, boolean createDirectory,
			FileAttribute<?>[] attrs) throws IOException {
		if (prefix == null)
			prefix = "";
		if (suffix == null)
			suffix = (createDirectory) ? "" : ".tmp";
		if (dir == null)
			dir = tmpdir;

		// in POSIX environments use default file and directory permissions
		// if initial permissions not given by caller.
		if (isPosix && (dir.getFileSystem() == FileSystems.getDefault())) {
			if (attrs.length == 0) {
				// no attributes so use default permissions
				attrs = new FileAttribute<?>[1];
				attrs[0] = (createDirectory) ? PosixPermissions.dirPermissions : PosixPermissions.filePermissions;
			} else {
				// check if posix permissions given; if not use default
				boolean hasPermissions = false;
				for (int i = 0; i < attrs.length; i++) {
					if (attrs[i].name().equals("posix:permissions")) {
						hasPermissions = true;
						break;
					}
				}
				if (!hasPermissions) {
					FileAttribute<?>[] copy = new FileAttribute<?>[attrs.length + 1];
					System.arraycopy(attrs, 0, copy, 0, attrs.length);
					attrs = copy;
					attrs[attrs.length - 1] = (createDirectory) ? PosixPermissions.dirPermissions
							: PosixPermissions.filePermissions;
				}
			}
		}

		// loop generating random names until file or directory can be created
		SecurityManager sm = System.getSecurityManager();
		//for (;;) {
			Path f;
			try {
				f = generatePath(prefix, suffix, dir);
			} catch (InvalidPathException e) {
				// don't reveal temporary directory location
				if (sm != null)
					throw new IllegalArgumentException("Invalid prefix or suffix");
				throw e;
			}
			try {
				if (createDirectory) {
					return Files.createDirectory(f, attrs);
				} else {
					return Files.createFile(f, attrs);
				}
			} catch (SecurityException e) {
				// don't reveal temporary directory location
				if (dir == tmpdir && sm != null)
					throw new SecurityException("Unable to create temporary file or directory");
				throw e;
			} catch (FileAlreadyExistsException e) {
				// FIXME Add the file deletion so we dont need this.
				// FIXME or make each test use a different folder...
				logger.debug("File found, reusing");
				return f;
				
			}
		//}
	}

	private static Path generatePath(String prefix, String suffix, Path dir) {
		Path name = dir.getFileSystem().getPath(prefix + suffix);
		// the generated name should be a simple file name
		if (name.getParent() != null)
			throw new IllegalArgumentException("Invalid prefix or suffix");
		return dir.resolve(name);
	}
}
