/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.commons.vfs2.provider.ftp;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.time.Instant;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.vfs2.FileName;
import org.apache.commons.vfs2.FileNotFolderException;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileType;
import org.apache.commons.vfs2.RandomAccessContent;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileObject;
import org.apache.commons.vfs2.provider.UriParser;
import org.apache.commons.vfs2.util.FileObjectUtils;
import org.apache.commons.vfs2.util.Messages;
import org.apache.commons.vfs2.util.MonitorInputStream;
import org.apache.commons.vfs2.util.MonitorOutputStream;
import org.apache.commons.vfs2.util.RandomAccessMode;

/**
 * An FTP file.
 */
public class FtpFileObject extends AbstractFileObject<FtpFileSystem> {

    /**
     * An InputStream that monitors for end-of-file.
     */
    class FtpInputStream extends MonitorInputStream {
        private final FtpClient client;

        public FtpInputStream(final FtpClient client, final InputStream in) {
            super(in);
            this.client = client;
        }

        public FtpInputStream(final FtpClient client, final InputStream in, final int bufferSize) {
            super(in, bufferSize);
            this.client = client;
        }

        void abort() throws IOException {
            client.abort();
            close();
        }

        private boolean isTransferAbortedOkReplyCode() throws IOException {
            final List<Integer> transferAbortedOkReplyCodes = FtpFileSystemConfigBuilder
                .getInstance()
                .getTransferAbortedOkReplyCodes(getAbstractFileSystem().getFileSystemOptions());
            return transferAbortedOkReplyCodes != null && transferAbortedOkReplyCodes.contains(client.getReplyCode());
        }

        /**
         * Called after the stream has been closed.
         */
        @Override
        protected void onClose() throws IOException {
            final boolean ok;
            try {
                ok = client.completePendingCommand() || isTransferAbortedOkReplyCode();
            } finally {
                getAbstractFileSystem().putClient(client);
            }

            if (!ok) {
                throw new FileSystemException("vfs.provider.ftp/finish-get.error", getName());
            }
        }
    }
    /**
     * An OutputStream that monitors for end-of-file.
     */
    private class FtpOutputStream extends MonitorOutputStream {
        private final FtpClient client;

        public FtpOutputStream(final FtpClient client, final OutputStream outstr) {
            super(outstr);
            this.client = client;
        }

        /**
         * Called after this stream is closed.
         */
        @Override
        protected void onClose() throws IOException {
            final boolean ok;
            try {
                ok = client.completePendingCommand();
            } finally {
                getAbstractFileSystem().putClient(client);
            }

            if (!ok) {
                throw new FileSystemException("vfs.provider.ftp/finish-put.error", getName());
            }
        }
    }
    private static final long DEFAULT_TIMESTAMP = 0L;
    private static final Map<String, FTPFile> EMPTY_FTP_FILE_MAP = Collections
            .unmodifiableMap(new TreeMap<String, FTPFile>());

    private static final FTPFile UNKNOWN = new FTPFile();

    private static final Log log = LogFactory.getLog(FtpFileObject.class);
    private volatile boolean mdtmSet;
    private final String relPath;
    // Cached info
    private volatile FTPFile ftpFile;
    private volatile Map<String, FTPFile> childMap;

    private volatile FileObject linkDestination;

    private final AtomicBoolean inRefresh = new AtomicBoolean();

    protected FtpFileObject(final AbstractFileName name, final FtpFileSystem fileSystem, final FileName rootName)
            throws FileSystemException {
        super(name, fileSystem);
        final String relPath = UriParser.decode(rootName.getRelativeName(name));
        if (".".equals(relPath)) {
            // do not use the "." as path against the ftp-server
            // e.g. the uu.net ftp-server do a recursive listing then
            // this.relPath = UriParser.decode(rootName.getPath());
            // this.relPath = ".";
            this.relPath = null;
        } else {
            this.relPath = relPath;
        }
    }

    /**
     * Attaches this file object to its file resource.
     */
    @Override
    protected void doAttach() throws IOException {
        // Get the parent folder to find the info for this file
        // VFS-210 getInfo(false);
    }

    /**
     * Creates this file as a folder.
     */
    @Override
    protected void doCreateFolder() throws Exception {
        final boolean ok;
        final FtpClient client = getAbstractFileSystem().getClient();
        try {
            ok = client.makeDirectory(relPath);
        } finally {
            getAbstractFileSystem().putClient(client);
        }

        if (!ok) {
            throw new FileSystemException("vfs.provider.ftp/create-folder.error", getName());
        }
    }

    /**
     * Deletes the file.
     */
    @Override
    protected void doDelete() throws Exception {
        synchronized (getFileSystem()) {
            if (this.ftpFile != null) {
                final boolean ok;
                final FtpClient ftpClient = getAbstractFileSystem().getClient();
                try {
                    if (this.ftpFile.isDirectory()) {
                        ok = ftpClient.removeDirectory(relPath);
                    } else {
                        ok = ftpClient.deleteFile(relPath);
                    }
                } finally {
                    getAbstractFileSystem().putClient(ftpClient);
                }

                if (!ok) {
                    throw new FileSystemException("vfs.provider.ftp/delete-file.error", getName());
                }
                this.ftpFile = null;
            }
            this.childMap = EMPTY_FTP_FILE_MAP;
        }
    }

    /**
     * Detaches this file object from its file resource.
     */
    @Override
    protected void doDetach() {
        synchronized (getFileSystem()) {
            this.ftpFile = null;
            this.childMap = null;
        }
    }

    /**
     * Fetches the children of this file, if not already cached.
     */
    private void doGetChildren() throws IOException {
        if (childMap != null) {
            return;
        }

        final FtpClient client = getAbstractFileSystem().getClient();
        try {
            final String path = ftpFile != null && ftpFile.isSymbolicLink()
                    ? getFileSystem().getFileSystemManager().resolveName(getParent().getName(), ftpFile.getLink())
                            .getPath()
                    : relPath;
            final FTPFile[] tmpChildren = client.listFiles(path);
            if (ArrayUtils.isEmpty(tmpChildren)) {
                childMap = EMPTY_FTP_FILE_MAP;
            } else {
                childMap = new TreeMap<>();

                // Remove '.' and '..' elements
                for (int i = 0; i < tmpChildren.length; i++) {
                    final FTPFile child = tmpChildren[i];
                    if (child == null) {
                        if (log.isDebugEnabled()) {
                            log.debug(Messages.getString("vfs.provider.ftp/invalid-directory-entry.debug",
                                    Integer.valueOf(i), relPath));
                        }
                        continue;
                    }
                    if (!".".equals(child.getName()) && !"..".equals(child.getName())) {
                        childMap.put(child.getName(), child);
                    }
                }
            }
        } finally {
            getAbstractFileSystem().putClient(client);
        }
    }

    /**
     * Returns the size of the file content (in bytes).
     */
    @Override
    protected long doGetContentSize() throws Exception {
        synchronized (getFileSystem()) {
            if (this.ftpFile == null) {
                return 0;
            }
            if (this.ftpFile.isSymbolicLink()) {
                final FileObject linkDest = getLinkDestination();
                // VFS-437: Try to avoid a recursion loop.
                if (this.isCircular(linkDest)) {
                    return this.ftpFile.getSize();
                }
                return linkDest.getContent().getSize();
            }
            return this.ftpFile.getSize();
        }
    }

    /**
     * Creates an input stream to read the file content from.
     */
    @Override
    protected InputStream doGetInputStream(final int bufferSize) throws Exception {
        final FtpClient client = getAbstractFileSystem().getClient();
        try {
            final InputStream inputStream = client.retrieveFileStream(relPath, 0);
            // VFS-210
            if (inputStream == null) {
                throw new FileNotFoundException(getName().toString());
            }
            return new FtpInputStream(client, inputStream, bufferSize);
        } catch (final Exception e) {
            getAbstractFileSystem().putClient(client);
            throw e;
        }
    }

    /**
     * Get the last modified time on an FTP file
     *
     * @see org.apache.commons.vfs2.provider.AbstractFileObject#doGetLastModifiedTime()
     */
    @Override
    protected long doGetLastModifiedTime() throws Exception {
        synchronized (getFileSystem()) {
            if (this.ftpFile == null) {
                return DEFAULT_TIMESTAMP;
            }
            if (this.ftpFile.isSymbolicLink()) {
                final FileObject linkDest = getLinkDestination();
                // VFS-437: Try to avoid a recursion loop.
                if (this.isCircular(linkDest)) {
                    return getTimestampMillis();
                }
                return linkDest.getContent().getLastModifiedTime();
            }
            return getTimestampMillis();
        }
    }

    /**
     * Creates an output stream to write the file content to.
     */
    @Override
    protected OutputStream doGetOutputStream(final boolean bAppend) throws Exception {
        final FtpClient client = getAbstractFileSystem().getClient();
        try {
            final OutputStream out;
            if (bAppend) {
                out = client.appendFileStream(relPath);
            } else {
                out = client.storeFileStream(relPath);
            }

            FileSystemException.requireNonNull(out, "vfs.provider.ftp/output-error.debug", this.getName(),
                    client.getReplyString());

            return new FtpOutputStream(client, out);
        } catch (final Exception e) {
            getAbstractFileSystem().putClient(client);
            throw e;
        }
    }

    @Override
    protected RandomAccessContent doGetRandomAccessContent(final RandomAccessMode mode) throws Exception {
        return new FtpRandomAccessContent(this, mode);
    }

    /**
     * Determines the type of the file, returns null if the file does not exist.
     */
    @Override
    protected FileType doGetType() throws Exception {
        // VFS-210
        synchronized (getFileSystem()) {
            if (this.ftpFile == null) {
                setFTPFile(false);
            }

            if (this.ftpFile == UNKNOWN) {
                return FileType.IMAGINARY;
            }
            if (this.ftpFile.isDirectory()) {
                return FileType.FOLDER;
            }
            if (this.ftpFile.isFile()) {
                return FileType.FILE;
            }
            if (this.ftpFile.isSymbolicLink()) {
                final FileObject linkDest = getLinkDestination();
                // VFS-437: We need to check if the symbolic link links back to the symbolic link itself
                if (this.isCircular(linkDest)) {
                    // If the symbolic link links back to itself, treat it as an imaginary file to prevent following
                    // this link. If the user tries to access the link as a file or directory, the user will end up with
                    // a FileSystemException warning that the file cannot be accessed. This is to prevent the infinite
                    // call back to doGetType() to prevent the StackOverFlow
                    return FileType.IMAGINARY;
                }
                return linkDest.getType();

            }
        }
        throw new FileSystemException("vfs.provider.ftp/get-type.error", getName());
    }

    /**
     * Lists the children of the file.
     */
    @Override
    protected String[] doListChildren() throws Exception {
        // List the children of this file
        doGetChildren();

        // VFS-210
        if (childMap == null) {
            return null;
        }

        // TODO - get rid of this children stuff
        final String[] childNames = childMap.values().stream().map(FTPFile::getName).toArray(String[]::new);

        return UriParser.encode(childNames);
    }

    @Override
    protected FileObject[] doListChildrenResolved() throws Exception {
        synchronized (getFileSystem()) {
            if (this.ftpFile != null && this.ftpFile.isSymbolicLink()) {
                final FileObject linkDest = getLinkDestination();
                // VFS-437: Try to avoid a recursion loop.
                if (this.isCircular(linkDest)) {
                    return null;
                }
                return linkDest.getChildren();
            }
        }
        return null;
    }

    /**
     * Renames the file
     */
    @Override
    protected void doRename(final FileObject newFile) throws Exception {
        synchronized (getFileSystem()) {
            final boolean ok;
            final FtpClient ftpClient = getAbstractFileSystem().getClient();
            try {
                final String newName = ((FtpFileObject) FileObjectUtils.getAbstractFileObject(newFile)).getRelPath();
                ok = ftpClient.rename(relPath, newName);
            } finally {
                getAbstractFileSystem().putClient(ftpClient);
            }

            if (!ok) {
                throw new FileSystemException("vfs.provider.ftp/rename-file.error", getName().toString(), newFile);
            }
            this.ftpFile = null;
            this.childMap = EMPTY_FTP_FILE_MAP;
        }
    }

    /**
     * Called by child file objects, to locate their FTP file info.
     *
     * @param name the file name in its native form ie. without URI stuff (%nn)
     * @param flush recreate children cache
     */
    private FTPFile getChildFile(final String name, final boolean flush) throws IOException {
        /*
         * If we should flush cached children, clear our children map unless we're in the middle of a refresh in which
         * case we've just recently refreshed our children. No need to do it again when our children are refresh()ed,
         * calling getChildFile() for themselves from within getInfo(). See getChildren().
         */
        if (flush && !inRefresh.get()) {
            childMap = null;
        }

        // List the children of this file
        doGetChildren();

        // Look for the requested child
        // VFS-210 adds the null check.
        return childMap != null ? childMap.get(name) : null;
    }

    /**
     * Returns the file's list of children.
     *
     * @return The list of children
     * @throws FileSystemException If there was a problem listing children
     * @see AbstractFileObject#getChildren()
     * @since 2.0
     */
    @Override
    public FileObject[] getChildren() throws FileSystemException {
        try {
            if (doGetType() != FileType.FOLDER) {
                throw new FileNotFolderException(getName());
            }
        } catch (final Exception ex) {
            throw new FileNotFolderException(getName(), ex);
        }

        try {
            /*
             * Wrap our parent implementation, noting that we're refreshing so that we don't refresh() ourselves and
             * each of our parents for each children. Note that refresh() will list children. Meaning, if if this file
             * has C children, P parents, there will be (C * P) listings made with (C * (P + 1)) refreshes, when there
             * should really only be 1 listing and C refreshes.
             */
            this.inRefresh.set(true);
            return super.getChildren();
        } finally {
            this.inRefresh.set(false);
        }
    }

    FtpInputStream getInputStream(final long filePointer) throws IOException {
        final FtpClient client = getAbstractFileSystem().getClient();
        try {
            final InputStream instr = client.retrieveFileStream(relPath, filePointer);
            FileSystemException.requireNonNull(instr, "vfs.provider.ftp/input-error.debug", this.getName(),
                    client.getReplyString());
            return new FtpInputStream(client, instr);
        } catch (final IOException e) {
            getAbstractFileSystem().putClient(client);
            throw e;
        }
    }

    private FileObject getLinkDestination() throws FileSystemException {
        if (linkDestination == null) {
            final String path;
            synchronized (getFileSystem()) {
                path = this.ftpFile == null ? null : this.ftpFile.getLink();
            }
            final FileName parent = getName().getParent();
            final FileName relativeTo = parent == null ? getName() : parent;
            final FileName linkDestinationName = getFileSystem().getFileSystemManager().resolveName(relativeTo, path);
            linkDestination = getFileSystem().resolveFile(linkDestinationName);
        }
        return linkDestination;
    }

    String getRelPath() {
        return relPath;
    }

    /**
     * ftpFile is not null.
     */
    @SuppressWarnings("resource") // abstractFileSystem is managed in the superclass.
    private long getTimestampMillis() throws IOException {
        final FtpFileSystem abstractFileSystem = getAbstractFileSystem();
        final Boolean mdtmLastModifiedTime = FtpFileSystemConfigBuilder.getInstance()
            .getMdtmLastModifiedTime(abstractFileSystem.getFileSystemOptions());
        if (mdtmLastModifiedTime != null && mdtmLastModifiedTime.booleanValue()) {
            final FtpClient client = abstractFileSystem.getClient();
            if (!mdtmSet && client.hasFeature("MDTM")) {
                final Instant mdtmInstant = client.mdtmInstant(relPath);
                final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
                final long epochMilli = mdtmInstant.toEpochMilli();
                calendar.setTimeInMillis(epochMilli);
                ftpFile.setTimestamp(calendar);
                mdtmSet = true;
            }
        }
        return ftpFile.getTimestamp().getTime().getTime();
    }

    /**
     * This is an over simplistic implementation for VFS-437.
     */
    private boolean isCircular(final FileObject linkDest) throws FileSystemException {
        return linkDest.getName().getPathDecoded().equals(this.getName().getPathDecoded());
    }

    /**
     * Called when the type or content of this file changes.
     */
    @Override
    protected void onChange() throws IOException {
        childMap = null;

        if (getType().equals(FileType.IMAGINARY)) {
            // file is deleted, avoid server lookup
            synchronized (getFileSystem()) {
                this.ftpFile = UNKNOWN;
            }
            return;
        }

        setFTPFile(true);
    }

    /**
     * Called when the children of this file change.
     */
    @Override
    protected void onChildrenChanged(final FileName child, final FileType newType) {
        if (childMap != null && newType.equals(FileType.IMAGINARY)) {
            try {
                childMap.remove(UriParser.decode(child.getBaseName()));
            } catch (final FileSystemException e) {
                throw new RuntimeException(e.getMessage());
            }
        } else {
            // if child was added we have to rescan the children
            // TODO - get rid of this
            childMap = null;
        }
    }

    /**
     * @throws FileSystemException if an error occurs.
     */
    @Override
    public void refresh() throws FileSystemException {
        if (inRefresh.compareAndSet(false, true)) {
            try {
                super.refresh();
                synchronized (getFileSystem()) {
                    this.ftpFile = null;
                }
                /*
                 * VFS-210 try { // this will tell the parent to recreate its children collection getInfo(true); } catch
                 * (IOException e) { throw new FileSystemException(e); }
                 */
            } finally {
                inRefresh.set(false);
            }
        }
    }

    /**
     * Sets the internal FTPFile for this instance.
     */
    private void setFTPFile(final boolean flush) throws IOException {
        synchronized (getFileSystem()) {
            final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
            final FTPFile newFileInfo;
            if (parent != null) {
                newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()), flush);
            } else {
                // Assume the root is a directory and exists
                newFileInfo = new FTPFile();
                newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
            }
            this.ftpFile = newFileInfo == null ? UNKNOWN : newFileInfo;
        }}
}
