package org.xbib.files.ftp.fs;

import java.nio.file.AccessDeniedException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemException;
import java.nio.file.NoSuchFileException;
import java.nio.file.OpenOption;
import java.util.Collection;

/**
 * A factory for creating {@link FileSystemException}s based on replies from an FTP server.
 * It's not always possible to distinguish different types of errors. For instance, a 550 error code (file unavailable) could indicate that a file
 * does not exist (which should trigger a {@link NoSuchFileException}), or that a file is inaccessible (which should trigger a
 * {@link AccessDeniedException}), or possibly another reason.
 * This interface allows users to provide their own mapping, based on both the reply code and the reply string from an FTP reply.
 * Ideally implementations return exceptions that implement {@link FTPResponse}.
 * This way, the original FTP reply code and message will be reserved.
 */
public interface FileSystemExceptionFactory {

    /**
     * Creates a {@code FileSystemException} that indicates a file or directory cannot be retrieved.
     * <p>
     * Note that the LIST command is used to retrieve a file or directory. This will often return with a 226 code even if a file or directory cannot
     * be retrieved. This does not mean that the LIST call was actually successful.
     *
     * @param file        A string identifying the file or directory.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createGetFileException(String file, int replyCode, String replyString);

    /**
     * Creates a {@code FileSystemException} that indicates a directory cannot be used as the current working directory.
     *
     * @param directory   A string identifying the directory.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createChangeWorkingDirectoryException(String directory, int replyCode, String replyString);

    /**
     * Creates a {@code FileSystemException} that indicates a directory cannot be created.
     *
     * @param directory   A string identifying the directory.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileAlreadyExistsException createCreateDirectoryException(String directory, int replyCode, String replyString);

    /**
     * Creates a {@code FileSystemException} that indicates a file or directory cannot be deleted.
     *
     * @param file        A string identifying the file or directory.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @param isDirectory {@code true} if a directory cannot be deleted, or {@code false} if a file cannot be deleted.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createDeleteException(String file, int replyCode, String replyString, boolean isDirectory);

    /**
     * Creates a {@code FileSystemException} that indicates a file cannot be opened for reading.
     *
     * @param file        A string identifying the file.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createNewInputStreamException(String file, int replyCode, String replyString);

    /**
     * Creates a {@code FileSystemException} that indicates a file cannot be opened for writing.
     *
     * @param file        A string identifying the file.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @param options     The open options used to open the file.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createNewOutputStreamException(String file, int replyCode, String replyString, Collection<? extends OpenOption> options);

    /**
     * Creates a {@code FileSystemException} that indicates a file or directory cannot be copied.
     *
     * @param file        A string identifying the file or directory to be copied.
     * @param other       A string identifying the file or directory to be copied to.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createCopyException(String file, String other, int replyCode, String replyString);

    /**
     * Creates a {@code FileSystemException} that indicates a file or directory cannot be moved.
     *
     * @param file        A string identifying the file or directory to be moved.
     * @param other       A string identifying the file or directory to be moved to.
     * @param replyCode   The integer value of the reply code of the last FTP reply that triggered this method call.
     * @param replyString The entire text from the last FTP response that triggered this method call.
     * @return The created {@code FileSystemException}.
     */
    FileSystemException createMoveException(String file, String other, int replyCode, String replyString);
}
