/*
 * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

import java.io.IOException;
import java.net.URI;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryIteratorException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.FileSystemAlreadyExistsException;
import java.nio.file.FileSystemNotFoundException;
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.PathMatcher;
import java.nio.file.WatchService;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.UserPrincipalLookupService;
import java.nio.file.spi.FileSystemProvider;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import java.util.function.Supplier;

/**
 * A {@code FileSystem} that helps testing by trigger exception throwing based on filenames.
 */
class FaultyFileSystem extends FileSystem {
    final Path root;
    final boolean removeRootAfterClose;
    final FileSystem delegate;
    boolean isOpen;

    FaultyFileSystem(Path root) throws IOException {
        if (root == null) {
            root = Files.createTempDirectory("faultyFS");
            removeRootAfterClose = true;
        } else {
            if (! Files.isDirectory(root)) {
                throw new IllegalArgumentException("must be a directory.");
            }
            removeRootAfterClose = false;
        }
        this.root = root;
        delegate = root.getFileSystem();
        isOpen = true;
    }

    private static Path unwrap(Path p) {
        return PassThroughFileSystem.unwrap(p);
    }

    Path getRoot() {
        return new PassThroughFileSystem.PassThroughPath(this, root);
    }

    @Override
    public void close() throws IOException {
        if (isOpen) {
            if (removeRootAfterClose) {
                TestUtil.removeAll(root);
            }
            isOpen = false;
        }
    }

    @Override
    public FileSystemProvider provider() {
        return FaultyFSProvider.getInstance();
    }

    @Override
    public boolean isOpen() {
        return isOpen;
    }

    @Override
    public boolean isReadOnly() {
        return delegate.isReadOnly();
    }

    @Override
    public String getSeparator() {
        return delegate.getSeparator();
    }

    private <T> Iterable<T> SoleIterable(final T element) {
        return new Iterable<T>() {
            @Override
            public Iterator<T> iterator() {
                return new Iterator<T>() {
                    private T soleElement = element;

                    @Override
                    public boolean hasNext() {
                        return soleElement != null;
                    }

                    @Override
                    public T next() {
                        try {
                            return soleElement;
                        } finally {
                            soleElement = null;
                        }
                    }
                };
            }
        };
    }

    @Override
    public Iterable<Path> getRootDirectories() {
        return SoleIterable(getRoot());
    }

    @Override
    public Iterable<FileStore> getFileStores() {
        FileStore store;
        try {
            store = Files.getFileStore(root);
        } catch (IOException ioe) {
            store = null;
        }
        return SoleIterable(store);
    }

    @Override
    public Set<String> supportedFileAttributeViews() {
        // assume that unwrapped objects aren't exposed
        return delegate.supportedFileAttributeViews();
    }

    @Override
    public Path getPath(String first, String... more) {
        return new PassThroughFileSystem.PassThroughPath(this, delegate.getPath(first, more));
    }

    @Override
    public PathMatcher getPathMatcher(String syntaxAndPattern) {
        final PathMatcher matcher = delegate.getPathMatcher(syntaxAndPattern);
        return new PathMatcher() {
            @Override
            public boolean matches(Path path) {
                return matcher.matches(unwrap(path));
            }
        };
    }

    @Override
    public UserPrincipalLookupService getUserPrincipalLookupService() {
        // assume that unwrapped objects aren't exposed
        return delegate.getUserPrincipalLookupService();
    }

    @Override
    public WatchService newWatchService() throws IOException {
        // to keep it simple
        throw new UnsupportedOperationException();
    }

    static class FaultyException extends IOException {
        FaultyException() {
            super("fault triggered.");
        }
    }

    static class FaultyFSProvider extends FileSystemProvider {
        private static final String SCHEME = "faulty";
        private static volatile FaultyFileSystem delegate;
        private static FaultyFSProvider INSTANCE = new FaultyFSProvider();
        private boolean enabled;

        private FaultyFSProvider() {}

        public static FaultyFSProvider getInstance() {
            return INSTANCE;
        }

        public void setFaultyMode(boolean enable) {
            enabled = enable;
        }

        private void triggerEx(String filename, String... names) throws IOException {
            if (! enabled) {
                return;
            }

            if (filename.equals("IOException")) {
                throw new FaultyException();
            }

            for (String name: names) {
                if (name.equals(filename)) {
                    throw new FaultyException();
                }
            }
        }

        private void triggerEx(Path path, String... names) throws IOException {
            triggerEx(path.getFileName().toString(), names);
        }

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

        private void checkScheme(URI uri) {
            if (!uri.getScheme().equalsIgnoreCase(SCHEME))
                throw new IllegalArgumentException();
        }

        private void checkUri(URI uri) {
            checkScheme(uri);
            if (!uri.getSchemeSpecificPart().equals("///"))
                throw new IllegalArgumentException();
        }

        @Override
        public FileSystem newFileSystem(Path fakeRoot, Map<String,?> env)
            throws IOException
        {
            if (env != null && env.keySet().contains("IOException")) {
                triggerEx("IOException");
            }

            synchronized (FaultyFSProvider.class) {
                if (delegate != null && delegate.isOpen())
                    throw new FileSystemAlreadyExistsException();
                FaultyFileSystem result = new FaultyFileSystem(fakeRoot);
                delegate = result;
                return result;
            }
        }

        @Override
        public FileSystem newFileSystem(URI uri, Map<String,?> env)
            throws IOException
        {
            if (env != null && env.keySet().contains("IOException")) {
                triggerEx("IOException");
            }

            checkUri(uri);
            synchronized (FaultyFSProvider.class) {
                if (delegate != null && delegate.isOpen())
                    throw new FileSystemAlreadyExistsException();
                FaultyFileSystem result = new FaultyFileSystem(null);
                delegate = result;
                return result;
            }
        }

        @Override
        public FileSystem getFileSystem(URI uri) {
            checkUri(uri);
            FileSystem result = delegate;
            if (result == null)
                throw new FileSystemNotFoundException();
            return result;
        }

        @Override
        public Path getPath(URI uri) {
            checkScheme(uri);
            if (delegate == null)
                throw new FileSystemNotFoundException();

            // only allow absolute path
            String path = uri.getSchemeSpecificPart();
            if (! path.startsWith("///")) {
                throw new IllegalArgumentException();
            }
            return new PassThroughFileSystem.PassThroughPath(delegate, delegate.root.resolve(path.substring(3)));
        }

        @Override
        public void setAttribute(Path file, String attribute, Object value, LinkOption... options)
            throws IOException
        {
            triggerEx(file, "setAttribute");
            Files.setAttribute(unwrap(file), attribute, value, options);
        }

        @Override
        public Map<String,Object> readAttributes(Path file, String attributes, LinkOption... options)
            throws IOException
        {
            triggerEx(file, "readAttributes");
            return Files.readAttributes(unwrap(file), attributes, options);
        }

        @Override
        public <V extends FileAttributeView> V getFileAttributeView(Path file,
                                                                    Class<V> type,
                                                                    LinkOption... options)
        {
            return Files.getFileAttributeView(unwrap(file), type, options);
        }

        @Override
        public <A extends BasicFileAttributes> A readAttributes(Path file,
                                                                Class<A> type,
                                                                LinkOption... options)
            throws IOException
        {
            triggerEx(file, "readAttributes");
            return Files.readAttributes(unwrap(file), type, options);
        }

        @Override
        public void delete(Path file) throws IOException {
            triggerEx(file, "delete");
            Files.delete(unwrap(file));
        }

        @Override
        public void createSymbolicLink(Path link, Path target, FileAttribute<?>... attrs)
            throws IOException
        {
            triggerEx(target, "createSymbolicLink");
            Files.createSymbolicLink(unwrap(link), unwrap(target), attrs);
        }

        @Override
        public void createLink(Path link, Path existing) throws IOException {
            triggerEx(existing, "createLink");
            Files.createLink(unwrap(link), unwrap(existing));
        }

        @Override
        public Path readSymbolicLink(Path link) throws IOException {
            Path target = Files.readSymbolicLink(unwrap(link));
            triggerEx(target, "readSymbolicLink");
            return new PassThroughFileSystem.PassThroughPath(delegate, target);
        }


        @Override
        public void copy(Path source, Path target, CopyOption... options) throws IOException {
            triggerEx(source, "copy");
            Files.copy(unwrap(source), unwrap(target), options);
        }

        @Override
        public void move(Path source, Path target, CopyOption... options) throws IOException {
            triggerEx(source, "move");
            Files.move(unwrap(source), unwrap(target), options);
        }

        private DirectoryStream<Path> wrap(final DirectoryStream<Path> stream) {
            return new DirectoryStream<Path>() {
                @Override
                public Iterator<Path> iterator() {
                    final Iterator<Path> itr = stream.iterator();
                    return new Iterator<Path>() {
                        private Path next = null;
                        @Override
                        public boolean hasNext() {
                            if (next == null) {
                                if (itr.hasNext()) {
                                    next = itr.next();
                                } else {
                                    return false;
                                }
                            }
                            if (next != null) {
                                try {
                                    triggerEx(next, "DirectoryIteratorException");
                                } catch (IOException ioe) {
                                    throw new DirectoryIteratorException(ioe);
                                }
                            }
                            return (next != null);
                        }
                        @Override
                        public Path next() {
                            try {
                                if (next != null || hasNext()) {
                                    return new PassThroughFileSystem.PassThroughPath(delegate, next);
                                } else {
                                    throw new NoSuchElementException();
                                }
                            } finally {
                                next = null;
                            }
                        }

                        @Override
                        public void remove() {
                            itr.remove();
                        }
                    };
                }
                @Override
                public void close() throws IOException {
                    stream.close();
                }
            };
        }

        @Override
        public DirectoryStream<Path> newDirectoryStream(Path dir, DirectoryStream.Filter<? super Path> filter)
            throws IOException
        {
            triggerEx(dir, "newDirectoryStream");
            return wrap(Files.newDirectoryStream(unwrap(dir), filter));
        }

        @Override
        public void createDirectory(Path dir, FileAttribute<?>... attrs)
            throws IOException
        {
            triggerEx(dir, "createDirectory");
            Files.createDirectory(unwrap(dir), attrs);
        }

        @Override
        public SeekableByteChannel newByteChannel(Path file,
                                                  Set<? extends OpenOption> options,
                                                  FileAttribute<?>... attrs)
            throws IOException
        {
            triggerEx(file, "newByteChannel");
            return Files.newByteChannel(unwrap(file), options, attrs);
        }


        @Override
        public boolean isHidden(Path file) throws IOException {
            triggerEx(file, "isHidden");
            return Files.isHidden(unwrap(file));
        }

        @Override
        public FileStore getFileStore(Path file) throws IOException {
            triggerEx(file, "getFileStore");
            return Files.getFileStore(unwrap(file));
        }

        @Override
        public boolean isSameFile(Path file, Path other) throws IOException {
            triggerEx(file, "isSameFile");
            return Files.isSameFile(unwrap(file), unwrap(other));
        }

        @Override
        public void checkAccess(Path file, AccessMode... modes)
            throws IOException
        {
            triggerEx(file, "checkAccess");
            // hack
            if (modes.length == 0) {
                if (Files.exists(unwrap(file)))
                    return;
                else
                    throw new NoSuchFileException(file.toString());
            }
            throw new RuntimeException("not implemented yet");
        }
    }
}
