/*
 * Copyright (c) 2007, 2009, 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * 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.
 */

package sun.nio.fs;

import java.nio.file.*;
import static java.nio.file.StandardOpenOption.*;
import java.nio.file.attribute.*;
import java.nio.channels.*;
import java.nio.ByteBuffer;
import java.io.*;
import java.util.*;

/**
 * Base implementation class for a {@code Path}.
 */

abstract class AbstractPath extends Path {
    protected AbstractPath() { }

    @Override
    public final Path createFile(FileAttribute<?>... attrs)
        throws IOException
    {
        EnumSet<StandardOpenOption> options = EnumSet.of(CREATE_NEW, WRITE);
        SeekableByteChannel sbc = newByteChannel(options, attrs);
        try {
            sbc.close();
        } catch (IOException x) {
            // ignore
        }
        return this;
    }

    /**
     * Deletes a file. The {@code failIfNotExists} parameters determines if an
     * {@code IOException} is thrown when the file does not exist.
     */
    abstract void implDelete(boolean failIfNotExists) throws IOException;

    @Override
    public final void delete() throws IOException {
        implDelete(true);
    }

    @Override
    public final void deleteIfExists() throws IOException {
        implDelete(false);
    }

    @Override
    public final InputStream newInputStream(OpenOption... options)
        throws IOException
    {
        if (options.length > 0) {
            for (OpenOption opt: options) {
                if (opt != READ)
                    throw new UnsupportedOperationException("'" + opt + "' not allowed");
            }
        }
        return Channels.newInputStream(newByteChannel());
    }

    @Override
    public final OutputStream newOutputStream(OpenOption... options)
        throws IOException
    {
        int len = options.length;
        Set<OpenOption> opts = new HashSet<OpenOption>(len + 3);
        if (len == 0) {
            opts.add(CREATE);
            opts.add(TRUNCATE_EXISTING);
        } else {
            for (OpenOption opt: options) {
                if (opt == READ)
                    throw new IllegalArgumentException("READ not allowed");
                opts.add(opt);
            }
        }
        opts.add(WRITE);
        return Channels.newOutputStream(newByteChannel(opts));
    }

    @Override
    public final SeekableByteChannel newByteChannel(OpenOption... options)
        throws IOException
    {
        Set<OpenOption> set = new HashSet<OpenOption>(options.length);
        Collections.addAll(set, options);
        return newByteChannel(set);
    }

    private static final DirectoryStream.Filter<Path> acceptAllFilter =
        new DirectoryStream.Filter<Path>() {
            @Override public boolean accept(Path entry) { return true; }
        };

    @Override
    public final DirectoryStream<Path> newDirectoryStream() throws IOException {
        return newDirectoryStream(acceptAllFilter);
    }

    @Override
    public final DirectoryStream<Path> newDirectoryStream(String glob)
        throws IOException
    {
        // avoid creating a matcher if all entries are required.
        if (glob.equals("*"))
            return newDirectoryStream();

        // create a matcher and return a filter that uses it.
        final PathMatcher matcher = getFileSystem().getPathMatcher("glob:" + glob);
        DirectoryStream.Filter<Path> filter = new DirectoryStream.Filter<Path>() {
            @Override
            public boolean accept(Path entry)  {
                return matcher.matches(entry.getName());
            }
        };
        return newDirectoryStream(filter);
    }

    @Override
    public final boolean exists() {
        try {
            checkAccess();
            return true;
        } catch (IOException x) {
            // unable to determine if file exists
        }
        return false;
    }

    @Override
    public final boolean notExists() {
        try {
            checkAccess();
            return false;
        } catch (NoSuchFileException x) {
            // file confirmed not to exist
            return true;
        } catch (IOException x) {
            return false;
        }
    }

    private static final WatchEvent.Modifier[] NO_MODIFIERS = new WatchEvent.Modifier[0];

    @Override
    public final WatchKey register(WatchService watcher,
                                   WatchEvent.Kind<?>... events)
        throws IOException
    {
        return register(watcher, events, NO_MODIFIERS);
    }

    abstract void implCopyTo(Path target, CopyOption... options)
        throws IOException;

    @Override
    public final Path copyTo(Path target, CopyOption... options)
        throws IOException
    {
        if ((getFileSystem().provider() == target.getFileSystem().provider())) {
            implCopyTo(target, options);
        } else {
            copyToForeignTarget(target, options);
        }
        return target;
    }

    abstract void implMoveTo(Path target, CopyOption... options)
        throws IOException;

    @Override
    public final Path moveTo(Path target, CopyOption... options)
        throws IOException
    {
        if ((getFileSystem().provider() == target.getFileSystem().provider())) {
            implMoveTo(target, options);
        } else {
            // different providers so copy + delete
            copyToForeignTarget(target, convertMoveToCopyOptions(options));
            delete();
        }
        return target;
    }

    /**
     * Converts the given array of options for moving a file to options suitable
     * for copying the file when a move is implemented as copy + delete.
     */
    private static CopyOption[] convertMoveToCopyOptions(CopyOption... options)
        throws AtomicMoveNotSupportedException
    {
        int len = options.length;
        CopyOption[] newOptions = new CopyOption[len+2];
        for (int i=0; i<len; i++) {
            CopyOption option = options[i];
            if (option == StandardCopyOption.ATOMIC_MOVE) {
                throw new AtomicMoveNotSupportedException(null, null,
                    "Atomic move between providers is not supported");
            }
            newOptions[i] = option;
        }
        newOptions[len] = LinkOption.NOFOLLOW_LINKS;
        newOptions[len+1] = StandardCopyOption.COPY_ATTRIBUTES;
        return newOptions;
    }

    /**
     * Parses the arguments for a file copy operation.
     */
    private static class CopyOptions {
        boolean replaceExisting = false;
        boolean copyAttributes = false;
        boolean followLinks = true;

        private CopyOptions() { }

        static CopyOptions parse(CopyOption... options) {
            CopyOptions result = new CopyOptions();
            for (CopyOption option: options) {
                if (option == StandardCopyOption.REPLACE_EXISTING) {
                    result.replaceExisting = true;
                    continue;
                }
                if (option == LinkOption.NOFOLLOW_LINKS) {
                    result.followLinks = false;
                    continue;
                }
                if (option == StandardCopyOption.COPY_ATTRIBUTES) {
                    result.copyAttributes = true;
                    continue;
                }
                if (option == null)
                    throw new NullPointerException();
                throw new UnsupportedOperationException("'" + option +
                    "' is not a recognized copy option");
            }
            return result;
        }
    }

    /**
     * Simple cross-provider copy where the target is a Path.
     */
    private void copyToForeignTarget(Path target, CopyOption... options)
        throws IOException
    {
        CopyOptions opts = CopyOptions.parse(options);
        LinkOption[] linkOptions = (opts.followLinks) ? new LinkOption[0] :
            new LinkOption[] { LinkOption.NOFOLLOW_LINKS };

        // attributes of source file
        BasicFileAttributes attrs = Attributes
            .readBasicFileAttributes(this, linkOptions);
        if (attrs.isSymbolicLink())
            throw new IOException("Copying of symbolic links not supported");

        // check if target exists
        boolean exists;
        if (opts.replaceExisting) {
            try {
                target.deleteIfExists();
                exists = false;
            } catch (DirectoryNotEmptyException x) {
                // let exception translate to FileAlreadyExistsException (6895012)
                exists = true;
            }
        } else {
            exists = target.exists();
        }
        if (exists)
            throw new FileAlreadyExistsException(target.toString());

        // create directory or file
        if (attrs.isDirectory()) {
            target.createDirectory();
        } else {
            copyRegularFileToForeignTarget(target);
        }

        // copy basic attributes to target
        if (opts.copyAttributes) {
            BasicFileAttributeView view = target
                .getFileAttributeView(BasicFileAttributeView.class, linkOptions);
            try {
                view.setTimes(attrs.lastModifiedTime(),
                              attrs.lastAccessTime(),
                              attrs.creationTime());
            } catch (IOException x) {
                // rollback
                try {
                    target.delete();
                } catch (IOException ignore) { }
                throw x;
            }
        }
    }


   /**
     * Simple copy of regular file to a target file that exists.
     */
    private void copyRegularFileToForeignTarget(Path target)
        throws IOException
    {
        ReadableByteChannel rbc = newByteChannel();
        try {
            // open target file for writing
            SeekableByteChannel sbc = target.newByteChannel(CREATE_NEW, WRITE);

            // simple copy loop
            try {
                ByteBuffer buf = ByteBuffer.wrap(new byte[8192]);
                int n = 0;
                for (;;) {
                    n = rbc.read(buf);
                    if (n < 0)
                        break;
                    assert n > 0;
                    buf.flip();
                    while (buf.hasRemaining()) {
                        sbc.write(buf);
                    }
                    buf.rewind();
                }

            } finally {
                sbc.close();
            }
        } finally {
            rbc.close();
        }
    }

    /**
     * Splits the given attribute name into the name of an attribute view and
     * the attribute. If the attribute view is not identified then it assumed
     * to be "basic".
     */
    private static String[] split(String attribute) {
        String[] s = new String[2];
        int pos = attribute.indexOf(':');
        if (pos == -1) {
            s[0] = "basic";
            s[1] = attribute;
        } else {
            s[0] = attribute.substring(0, pos++);
            s[1] = (pos == attribute.length()) ? "" : attribute.substring(pos);
        }
        return s;
    }

    /**
     * Gets a DynamicFileAttributeView by name. Returns {@code null} if the
     * view is not available.
     */
    abstract DynamicFileAttributeView getFileAttributeView(String name,
                                                           LinkOption... options);

    @Override
    public final void setAttribute(String attribute,
                                   Object value,
                                   LinkOption... options)
        throws IOException
    {
        String[] s = split(attribute);
        DynamicFileAttributeView view = getFileAttributeView(s[0], options);
        if (view == null)
            throw new UnsupportedOperationException("View '" + s[0] + "' not available");
        view.setAttribute(s[1], value);
    }

    @Override
    public final Object getAttribute(String attribute, LinkOption... options)
        throws IOException
    {
        String[] s = split(attribute);
        DynamicFileAttributeView view = getFileAttributeView(s[0], options);
        return (view == null) ? null : view.getAttribute(s[1]);
    }

    @Override
    public final Map<String,?> readAttributes(String attributes, LinkOption... options)
        throws IOException
    {
        String[] s = split(attributes);
        DynamicFileAttributeView view = getFileAttributeView(s[0], options);
        if (view == null)
            return Collections.emptyMap();
        return view.readAttributes(s[1].split(","));
    }
}
