package org.purl.wf4ever.robundle.fs;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.SeekableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.nio.charset.Charset;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystemNotFoundException;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.spi.FileSystemProvider;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.zip.CRC32;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import org.purl.wf4ever.robundle.utils.TemporaryFiles;

public class BundleFileSystemProvider extends FileSystemProvider {
	public class BundleFileChannel extends FileChannel {

		@SuppressWarnings("unused")
		private FileAttribute<?>[] attrs;
		private FileChannel fc;
		@SuppressWarnings("unused")
		private Set<? extends OpenOption> options;
		@SuppressWarnings("unused")
		private Path path;

		public BundleFileChannel(FileChannel fc, Path path,
				Set<? extends OpenOption> options, FileAttribute<?>[] attrs) {
			this.fc = fc;
			this.path = path;
			this.options = options;
			this.attrs = attrs;
		}

		public void force(boolean metaData) throws IOException {
			fc.force(metaData);
		}

		@Override
		protected void implCloseChannel() throws IOException {
			fc.close();
			// TODO: Update manifest
		}

		public FileLock lock(long position, long size, boolean shared)
				throws IOException {
			return fc.lock(position, size, shared);
		}

		public MappedByteBuffer map(MapMode mode, long position, long size)
				throws IOException {
			return fc.map(mode, position, size);
		}

		public long position() throws IOException {
			return fc.position();
		}

		public FileChannel position(long newPosition) throws IOException {
			return fc.position(newPosition);
		}

		public int read(ByteBuffer dst) throws IOException {
			return fc.read(dst);
		}

		public int read(ByteBuffer dst, long position) throws IOException {
			return fc.read(dst, position);
		}

		public long read(ByteBuffer[] dsts, int offset, int length)
				throws IOException {
			return fc.read(dsts, offset, length);
		}

		public long size() throws IOException {
			return fc.size();
		}

		public long transferFrom(ReadableByteChannel src, long position,
				long count) throws IOException {
			return fc.transferFrom(src, position, count);
		}

		public long transferTo(long position, long count,
				WritableByteChannel target) throws IOException {
			return fc.transferTo(position, count, target);
		}

		public FileChannel truncate(long size) throws IOException {
			return fc.truncate(size);
		}

		public FileLock tryLock(long position, long size, boolean shared)
				throws IOException {
			return fc.tryLock(position, size, shared);
		}

		public int write(ByteBuffer src) throws IOException {
			return fc.write(src);
		}

		public int write(ByteBuffer src, long position) throws IOException {
			return fc.write(src, position);
		}

		public long write(ByteBuffer[] srcs, int offset, int length)
				throws IOException {
			return fc.write(srcs, offset, length);
		}

	}

	private static class Singleton {
		// Fallback for OSGi environments
		private static final BundleFileSystemProvider INSTANCE = new BundleFileSystemProvider();
	}

	private static final String APP = "app";

	public static final String APPLICATION_VND_WF4EVER_ROBUNDLE_ZIP = "application/vnd.wf4ever.robundle+zip";
	public static final String MIMETYPE_FILE = "mimetype";

	/**
	 * The list of open file systems. This is static so that it is shared across
	 * eventual multiple instances of this provider (such as when running in an
	 * OSGi environment). Access to this map should be synchronized to avoid
	 * opening a file system that is not in the map.
	 */
	protected static Map<URI, WeakReference<BundleFileSystem>> openFilesystems = new HashMap<>();

	private static final Charset UTF8 = Charset.forName("UTF-8");

	protected static void addMimeTypeToZip(ZipOutputStream out, String mimetype)
			throws IOException {
		if (mimetype == null) {
			mimetype = APPLICATION_VND_WF4EVER_ROBUNDLE_ZIP;
		}
		// FIXME: Make the mediatype a parameter
		byte[] bytes = mimetype.getBytes(UTF8);

		// We'll have to do the mimetype file quite low-level
		// in order to ensure it is STORED and not COMPRESSED

		ZipEntry entry = new ZipEntry(MIMETYPE_FILE);
		entry.setMethod(ZipEntry.STORED);
		entry.setSize(bytes.length);
		CRC32 crc = new CRC32();
		crc.update(bytes);
		entry.setCrc(crc.getValue());

		out.putNextEntry(entry);
		out.write(bytes);
		out.closeEntry();
	}

	protected static void createBundleAsZip(Path bundle, String mimetype)
			throws FileNotFoundException, IOException {
		// Create ZIP file as
		// http://docs.oracle.com/javase/7/docs/technotes/guides/io/fsp/zipfilesystemprovider.html
		try (ZipOutputStream out = new ZipOutputStream(Files.newOutputStream(
				bundle, StandardOpenOption.CREATE,
				StandardOpenOption.TRUNCATE_EXISTING))) {
			addMimeTypeToZip(out, mimetype);
		}
	}

	public static BundleFileSystemProvider getInstance() {
		for (FileSystemProvider provider : FileSystemProvider
				.installedProviders()) {
			if (provider instanceof BundleFileSystemProvider) {
				return (BundleFileSystemProvider) provider;
			}
		}
		// Not installed!
		// Fallback for OSGi environments
		return Singleton.INSTANCE;
	}

	public static BundleFileSystem newFileSystemFromExisting(Path bundle)
			throws FileNotFoundException, IOException {
		URI w;
		try {
			w = new URI(APP, bundle.toUri().toASCIIString(), null);
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException("Can't create app: URI for "
					+ bundle);
		}

		Map<String, Object> options = new HashMap<>();

		// useTempFile not needed as we override
		// newByteChannel to use newFileChannel() - which don't
		// consume memory
		// options.put("useTempFile", true);

		FileSystem fs = FileSystems.newFileSystem(w, options,
				BundleFileSystemProvider.class.getClassLoader());
		return (BundleFileSystem) fs;

		// To avoid multiple instances of this provider in an OSGi environment,
		// the above official API calls could be replaced with:

		// return getInstance().newFileSystem(w, Collections.<String, Object>
		// emptyMap());

		// which would fall back to Singleton.INSTANCE if there is no provider.
	}

	public static BundleFileSystem newFileSystemFromNew(Path bundle)
			throws FileNotFoundException, IOException {
		return newFileSystemFromNew(bundle,
				APPLICATION_VND_WF4EVER_ROBUNDLE_ZIP);
	}

	public static BundleFileSystem newFileSystemFromNew(Path bundle,
			String mimetype) throws FileNotFoundException, IOException {
		createBundleAsZip(bundle, mimetype);
		return newFileSystemFromExisting(bundle);
	}

	public static BundleFileSystem newFileSystemFromTemporary()
			throws IOException {
		Path bundle = TemporaryFiles.temporaryBundle();
		BundleFileSystem fs = BundleFileSystemProvider.newFileSystemFromNew(
				bundle, null);
		return fs;
	}

	private Boolean jarDoubleEscaping;

	/**
	 * Public constructor provided for FileSystemProvider.installedProviders().
	 * Use #getInstance() instead.
	 * 
	 * @deprecated
	 */
	@Deprecated
	public BundleFileSystemProvider() {
	}

	private boolean asBoolean(Object object, boolean defaultValue) {
		if (object instanceof Boolean) {
			return (Boolean) object;
		}
		if (object instanceof String) {
			return Boolean.valueOf((String) object);
		}
		return defaultValue;
	}

	protected URI baseURIFor(URI uri) {
		if (!(uri.getScheme().equals(APP))) {
			throw new IllegalArgumentException("Unsupported scheme in: " + uri);
		}
		if (!uri.isOpaque()) {
			return uri.resolve("/");
		}
		Path localPath = localPathFor(uri);
		Path realPath;
		try {
			realPath = localPath.toRealPath();
		} catch (IOException ex) {
			realPath = localPath.toAbsolutePath();
		}
		// Generate a UUID from the MD5 of the URI of the real path (!)
		UUID uuid = UUID.nameUUIDFromBytes(realPath.toUri().toASCIIString()
				.getBytes(UTF8));
		try {
			return new URI(APP, uuid.toString(), "/", null);
		} catch (URISyntaxException e) {
			throw new IllegalStateException("Can't create app:// URI for: "
					+ uuid);
		}
	}

	@Override
	public void checkAccess(Path path, AccessMode... modes) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		origProvider(path).checkAccess(fs.unwrap(path), modes);
	}

	@Override
	public void copy(Path source, Path target, CopyOption... options)
			throws IOException {
		BundleFileSystem fs = (BundleFileSystem) source.getFileSystem();
		origProvider(source)
				.copy(fs.unwrap(source), fs.unwrap(target), options);
	}

	@Override
	public void createDirectory(Path dir, FileAttribute<?>... attrs)
			throws IOException {
		// Workaround http://stackoverflow.com/questions/16588321/
		if (Files.exists(dir)) {
			throw new FileAlreadyExistsException(dir.toString());
		}
		BundleFileSystem fs = (BundleFileSystem) dir.getFileSystem();
		origProvider(dir).createDirectory(fs.unwrap(dir), attrs);
	}

	@Override
	public void delete(Path path) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		origProvider(path).delete(fs.unwrap(path));
	}

	@Override
	public boolean equals(Object obj) {
		return getClass() == obj.getClass();
	}

	@Override
	public <V extends FileAttributeView> V getFileAttributeView(Path path,
			Class<V> type, LinkOption... options) {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		if (path.toAbsolutePath().equals(fs.getRootDirectory())) {
			// Bug in ZipFS, it will fall over as there is no entry for /
			//
			// Instead we'll just give a view of the source (e.g. the zipfile
			// itself).
			// Modifying its times is a bit futile since they are likely to be
			// overriden when closing, but this avoids a NullPointerException
			// in Files.setTimes().
			return Files.getFileAttributeView(fs.getSource(), type, options);
		}
		return origProvider(path).getFileAttributeView(fs.unwrap(path), type,
				options);
	}

	@Override
	public FileStore getFileStore(Path path) throws IOException {
		BundlePath bpath = (BundlePath) path;
		return bpath.getFileSystem().getFileStore();
	}

	@Override
	public BundleFileSystem getFileSystem(URI uri) {
		synchronized (openFilesystems) {
			URI baseURI = baseURIFor(uri);
			WeakReference<BundleFileSystem> ref = openFilesystems.get(baseURI);
			if (ref == null) {
				throw new FileSystemNotFoundException(uri.toString());
			}
			BundleFileSystem fs = ref.get();
			if (fs == null) {
				openFilesystems.remove(baseURI);
				throw new FileSystemNotFoundException(uri.toString());
			}
			return fs;
		}
	}

	protected boolean getJarDoubleEscaping() {
		if (jarDoubleEscaping != null) {
			return jarDoubleEscaping;
		}
		// https://bugs.openjdk.java.net/browse/JDK-8001178 introduced an
		// inconsistent
		// URI syntax. Before 7u40, jar: URIs to ZipFileSystemProvided had to
		// have
		// double-escaped the URI for the ZIP file, after 7u40 it is only
		// escaped once.
		// E.g.
		// to open before 7u40 you needed
		// jar:file:///file%2520with%2520spaces.zip, now you need
		// jar:file:///file%20with%20spaces.zip
		//
		// The new format is now consistent with URL.openStream() and
		// URLClassLoader's traditional jar: syntax, but somehow
		// zippath.toUri() still returns the double-escaped one, which
		// should only affects BundleFileSystem.findSource(). To help
		// findSource()
		// if this new bug is later fixed, we here detect which escaping style
		// is used.

		String name = "jar test";
		try {
			Path tmp = Files.createTempFile(name, ".zip");
			if (!tmp.toUri().toASCIIString().contains("jar%20test")) {
				// Hmm.. spaces not allowed in tmp? As we don't know, we'll
				// assume Java 7 behaviour
				jarDoubleEscaping = false;
				return jarDoubleEscaping;
			}
			createBundleAsZip(tmp, null);
			try (FileSystem fs = FileSystems.newFileSystem(tmp, null)) {
				URI root = fs.getRootDirectories().iterator().next().toUri();
				if (root.toASCIIString().contains("jar%2520test")) {
					jarDoubleEscaping = true;
				} else {
					jarDoubleEscaping = false;
				}
			}
			Files.delete(tmp);
		} catch (IOException e) {
			// Unknown error.. we'll assume Java 7 behaviour
			jarDoubleEscaping = true;
		}
		return jarDoubleEscaping;

	}

	@Override
	public Path getPath(URI uri) {
		BundleFileSystem fs = getFileSystem(uri);
		Path r = fs.getRootDirectory();
		if (uri.isOpaque()) {
			return r;
		} else {
			return r.resolve(uri.getPath());
		}
	}

	@Override
	public String getScheme() {
		return APP;
	}

	@Override
	public int hashCode() {
		return getClass().hashCode();
	}

	@Override
	public boolean isHidden(Path path) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		return origProvider(path).isHidden(fs.unwrap(path));
	}

	@Override
	public boolean isSameFile(Path path, Path path2) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		return origProvider(path).isSameFile(fs.unwrap(path), fs.unwrap(path2));
	}

	private Path localPathFor(URI uri) {
		URI localUri = URI.create(uri.getSchemeSpecificPart());
		return Paths.get(localUri);
	}

	@Override
	public void move(Path source, Path target, CopyOption... options)
			throws IOException {
		BundleFileSystem fs = (BundleFileSystem) source.getFileSystem();
		origProvider(source)
				.copy(fs.unwrap(source), fs.unwrap(target), options);
	}

	@Override
	public SeekableByteChannel newByteChannel(Path path,
			Set<? extends OpenOption> options, FileAttribute<?>... attrs)
			throws IOException {
		final BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		Path zipPath = fs.unwrap(path);
		if (options.contains(StandardOpenOption.WRITE)
				|| options.contains(StandardOpenOption.APPEND)) {

			if (Files.isDirectory(zipPath)) {
				// Workaround for ZIPFS allowing dir and folder to somewhat
				// co-exist
				throw new FileAlreadyExistsException("Directory <"
						+ zipPath.toString() + "> exists");
			}
			Path parent = zipPath.getParent();

			if (parent != null && !Files.isDirectory(parent)) {
				throw new NoSuchFileException(zipPath.toString(),
						parent.toString(), "Parent of file is not a directory");
			}
			if (options.contains(StandardOpenOption.CREATE_NEW)) {
			} else if (options.contains(StandardOpenOption.CREATE)
					&& !Files.exists(zipPath)) {
				// Workaround for bug in ZIPFS in Java 7 -
				// it only creates new files on
				// StandardOpenOption.CREATE_NEW
				//
				// We'll fake it and just create file first using the legacy
				// newByteChannel()
				// - we can't inject CREATE_NEW option as it
				// could be that there are two concurrent calls to CREATE
				// the very same file,
				// with CREATE_NEW the second thread would then fail.

				EnumSet<StandardOpenOption> opts = EnumSet
						.of(StandardOpenOption.WRITE,
								StandardOpenOption.CREATE_NEW);
				origProvider(path).newFileChannel(zipPath, opts, attrs).close();

			}
		}

		// Implement by newFileChannel to avoid memory leaks and
		// allow manifest to be updated
		return newFileChannel(path, options, attrs);
	}

	@Override
	public DirectoryStream<Path> newDirectoryStream(Path dir,
			final Filter<? super Path> filter) throws IOException {
		final BundleFileSystem fs = (BundleFileSystem) dir.getFileSystem();
		final DirectoryStream<Path> stream = origProvider(dir)
				.newDirectoryStream(fs.unwrap(dir), new Filter<Path>() {
					@Override
					public boolean accept(Path entry) throws IOException {
						return filter.accept(fs.wrap(entry));
					}
				});
		return new DirectoryStream<Path>() {
			@Override
			public void close() throws IOException {
				stream.close();
			}

			@Override
			public Iterator<Path> iterator() {
				return fs.wrapIterator(stream.iterator());
			}
		};
	}

	@Override
	public FileChannel newFileChannel(Path path,
			Set<? extends OpenOption> options, FileAttribute<?>... attrs)
			throws IOException {
		final BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		FileChannel fc = origProvider(path).newFileChannel(fs.unwrap(path),
				options, attrs);
		return new BundleFileChannel(fc, path, options, attrs);
	}

	@Override
	public FileSystem newFileSystem(Path path, Map<String, ?> env)
			throws IOException {
		URI uri;
		try {
			uri = new URI(APP, path.toUri().toASCIIString(), null);
		} catch (URISyntaxException e) {
			throw new IllegalArgumentException("Can't create app: URI for "
					+ path);
		}
		return newFileSystem(uri, env);
	}

	@Override
	public BundleFileSystem newFileSystem(URI uri, Map<String, ?> env)
			throws IOException {

		Path localPath = localPathFor(uri);
		URI baseURI = baseURIFor(uri);

		if (asBoolean(env.get("create"), false)) {
			createBundleAsZip(localPath, (String) env.get("mimetype"));
		}

		BundleFileSystem fs;
		synchronized (openFilesystems) {
			WeakReference<BundleFileSystem> existingRef = openFilesystems
					.get(baseURI);
			if (existingRef != null) {
				BundleFileSystem existing = existingRef.get();
				if (existing != null && existing.isOpen()) {
					throw new FileSystemAlreadyExistsException(
							baseURI.toASCIIString());
				}
			}
			FileSystem origFs = FileSystems.newFileSystem(localPath, null);
			fs = new BundleFileSystem(origFs, baseURI);
			openFilesystems.put(baseURI,
					new WeakReference<BundleFileSystem>(fs));
		}
		return fs;
	}

	@Override
	public InputStream newInputStream(Path path, OpenOption... options)
			throws IOException {
		// Avoid copying out to a file, like newByteChannel / newFileChannel
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		return origProvider(path).newInputStream(fs.unwrap(path), options);
	}

	@Override
	public OutputStream newOutputStream(Path path, OpenOption... options)
			throws IOException {
		BundleFileSystem fileSystem = (BundleFileSystem) path.getFileSystem();
		if (fileSystem.getRootDirectory().resolve(path)
				.equals(fileSystem.getRootDirectory().resolve(MIMETYPE_FILE))) {
			// Special case to avoid compression
			return origProvider(path).newOutputStream(fileSystem.unwrap(path),
					options);
		}
		return super.newOutputStream(path, options);
	}

	private FileSystemProvider origProvider(Path path) {
		return ((BundlePath) path).getFileSystem().getOrigFS().provider();
	}

	@Override
	public <A extends BasicFileAttributes> A readAttributes(Path path,
			Class<A> type, LinkOption... options) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		return origProvider(path)
				.readAttributes(fs.unwrap(path), type, options);
	}

	@Override
	public Map<String, Object> readAttributes(Path path, String attributes,
			LinkOption... options) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		return origProvider(path).readAttributes(fs.unwrap(path), attributes,
				options);
	}

	@Override
	public void setAttribute(Path path, String attribute, Object value,
			LinkOption... options) throws IOException {
		BundleFileSystem fs = (BundleFileSystem) path.getFileSystem();
		origProvider(path).setAttribute(fs.unwrap(path), attribute, value,
				options);
	}

}
