/*
 * 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.sshd.common.scp;

import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.StreamCorruptedException;
import java.nio.charset.StandardCharsets;
import java.nio.file.AccessDeniedException;
import java.nio.file.DirectoryStream;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.InvalidPathException;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributeView;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileTime;
import java.nio.file.attribute.PosixFilePermission;
import java.util.Collection;
import java.util.EnumSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.sshd.common.SshException;
import org.apache.sshd.common.file.util.MockPath;
import org.apache.sshd.common.scp.ScpTransferEventListener.FileOperation;
import org.apache.sshd.common.scp.helpers.DefaultScpFileOpener;
import org.apache.sshd.common.scp.helpers.LocalFileScpSourceStreamResolver;
import org.apache.sshd.common.scp.helpers.LocalFileScpTargetStreamResolver;
import org.apache.sshd.common.session.Session;
import org.apache.sshd.common.session.SessionHolder;
import org.apache.sshd.common.util.GenericUtils;
import org.apache.sshd.common.util.SelectorUtils;
import org.apache.sshd.common.util.ValidateUtils;
import org.apache.sshd.common.util.io.DirectoryScanner;
import org.apache.sshd.common.util.io.IoUtils;
import org.apache.sshd.common.util.io.LimitInputStream;
import org.apache.sshd.common.util.logging.AbstractLoggingBean;

/**
 * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
 */
public class ScpHelper extends AbstractLoggingBean implements SessionHolder<Session> {
    /**
     * Command prefix used to identify SCP commands
     */
    public static final String SCP_COMMAND_PREFIX = "scp";

    public static final int OK = 0;
    public static final int WARNING = 1;
    public static final int ERROR = 2;

    /**
     * Default size (in bytes) of send / receive buffer size
     */
    public static final int DEFAULT_COPY_BUFFER_SIZE = IoUtils.DEFAULT_COPY_SIZE;
    public static final int DEFAULT_RECEIVE_BUFFER_SIZE = DEFAULT_COPY_BUFFER_SIZE;
    public static final int DEFAULT_SEND_BUFFER_SIZE = DEFAULT_COPY_BUFFER_SIZE;

    /**
     * The minimum size for sending / receiving files
     */
    public static final int MIN_COPY_BUFFER_SIZE = Byte.MAX_VALUE;
    public static final int MIN_RECEIVE_BUFFER_SIZE = MIN_COPY_BUFFER_SIZE;
    public static final int MIN_SEND_BUFFER_SIZE = MIN_COPY_BUFFER_SIZE;

    public static final int S_IRUSR = 0000400;
    public static final int S_IWUSR = 0000200;
    public static final int S_IXUSR = 0000100;
    public static final int S_IRGRP = 0000040;
    public static final int S_IWGRP = 0000020;
    public static final int S_IXGRP = 0000010;
    public static final int S_IROTH = 0000004;
    public static final int S_IWOTH = 0000002;
    public static final int S_IXOTH = 0000001;

    protected final InputStream in;
    protected final OutputStream out;
    protected final FileSystem fileSystem;
    protected final ScpFileOpener opener;
    protected final ScpTransferEventListener listener;

    private final Session sessionInstance;

    public ScpHelper(Session session, InputStream in, OutputStream out,
            FileSystem fileSystem, ScpFileOpener opener, ScpTransferEventListener eventListener) {
        this.sessionInstance = ValidateUtils.checkNotNull(session, "No session");
        this.in = ValidateUtils.checkNotNull(in, "No input stream");
        this.out = ValidateUtils.checkNotNull(out, "No output stream");
        this.fileSystem = fileSystem;
        this.opener = (opener == null) ? DefaultScpFileOpener.INSTANCE : opener;
        this.listener = (eventListener == null) ? ScpTransferEventListener.EMPTY : eventListener;
    }

    @Override
    public Session getSession() {
        return sessionInstance;
    }

    public void receiveFileStream(final OutputStream local, final int bufferSize) throws IOException {
        receive(new ScpReceiveLineHandler() {
            @Override
            public void process(final String line, boolean isDir, ScpTimestamp timestamp) throws IOException {
                if (isDir) {
                    throw new StreamCorruptedException("Cannot download a directory into a file stream: " + line);
                }

                final Path path = new MockPath(line);
                receiveStream(line, new ScpTargetStreamResolver() {
                    @SuppressWarnings("synthetic-access")
                    @Override
                    public OutputStream resolveTargetStream(Session session, String name, long length,
                            Set<PosixFilePermission> perms, OpenOption... options) throws IOException {
                        if (log.isDebugEnabled()) {
                            log.debug("resolveTargetStream({}) name={}, perms={}, len={} - started local stream download",
                                      ScpHelper.this, name, perms, length);
                        }
                        return local;
                    }

                    @Override
                    public Path getEventListenerFilePath() {
                        return path;
                    }

                    @Override
                    @SuppressWarnings("synthetic-access")
                    public void postProcessReceivedData(String name, boolean preserve, Set<PosixFilePermission> perms, ScpTimestamp time) throws IOException {
                        if (log.isDebugEnabled()) {
                            log.debug("postProcessReceivedData({}) name={}, perms={}, preserve={} time={}",
                                      ScpHelper.this, name, perms, preserve, time);
                        }
                    }

                    @Override
                    public String toString() {
                        return line;
                    }
                }, timestamp, false, bufferSize);
            }
        });
    }

    public void receive(Path local, final boolean recursive, boolean shouldBeDir, final boolean preserve, final int bufferSize) throws IOException {
        final Path path = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        if (shouldBeDir) {
            LinkOption[] options = IoUtils.getLinkOptions(false);
            Boolean status = IoUtils.checkFileExists(path, options);
            if (status == null) {
                throw new SshException("Target directory " + path + " is most like inaccessible");
            }
            if (!status) {
                throw new SshException("Target directory " + path + " does not exist");
            }
            if (!Files.isDirectory(path, options)) {
                throw new SshException("Target directory " + path + " is not a directory");
            }
        }

        receive(new ScpReceiveLineHandler() {
            @Override
            public void process(String line, boolean isDir, ScpTimestamp time) throws IOException {
                if (recursive && isDir) {
                    receiveDir(line, path, time, preserve, bufferSize);
                } else {
                    receiveFile(line, path, time, preserve, bufferSize);
                }
            }
        });
    }

    protected void receive(ScpReceiveLineHandler handler) throws IOException {
        ack();
        ScpTimestamp time = null;
        for (;;) {
            String line;
            boolean isDir = false;
            int c = readAck(true);
            switch (c) {
                case -1:
                    return;
                case 'D':
                    isDir = true;
                    line = String.valueOf((char) c) + readLine();
                    if (log.isDebugEnabled()) {
                        log.debug("receive({}) - Received 'D' header: {}", this, line);
                    }
                    break;
                case 'C':
                    line = String.valueOf((char) c) + readLine();
                    if (log.isDebugEnabled()) {
                        log.debug("receive({}) - Received 'C' header: {}", this, line);
                    }
                    break;
                case 'T':
                    line = String.valueOf((char) c) + readLine();
                    if (log.isDebugEnabled()) {
                        log.debug("receive({}) - Received 'T' header: {}", this, line);
                    }
                    time = ScpTimestamp.parseTime(line);
                    ack();
                    continue;
                case 'E':
                    line = String.valueOf((char) c) + readLine();
                    if (log.isDebugEnabled()) {
                        log.debug("receive({}) - Received 'E' header: {}", this, line);
                    }
                    ack();
                    return;
                default:
                    //a real ack that has been acted upon already
                    continue;
            }

            try {
                handler.process(line, isDir, time);
            } finally {
                time = null;
            }
        }
    }

    public void receiveDir(String header, Path local, ScpTimestamp time, boolean preserve, int bufferSize) throws IOException {
        Path path = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        if (log.isDebugEnabled()) {
            log.debug("receiveDir({})[{}] Receiving directory {} - preserve={}, time={}, buffer-size={}",
                      this, header, path, preserve, time, bufferSize);
        }
        if (!header.startsWith("D")) {
            throw new IOException("Expected a 'D; message but got '" + header + "'");
        }

        Set<PosixFilePermission> perms = parseOctalPermissions(header.substring(1, 5));
        int length = Integer.parseInt(header.substring(6, header.indexOf(' ', 6)));
        String name = header.substring(header.indexOf(' ', 6) + 1);

        if (length != 0) {
            throw new IOException("Expected 0 length for directory but got " + length);
        }

        LinkOption[] options = IoUtils.getLinkOptions(false);
        Boolean status = IoUtils.checkFileExists(path, options);
        if (status == null) {
            throw new AccessDeniedException("Receive directory existence status cannot be determined: " + path);
        }

        Path file = null;
        if (status && Files.isDirectory(path, options)) {
            String localName = name.replace('/', File.separatorChar);
            file = path.resolve(localName);
        } else if (!status) {
            Path parent = path.getParent();

            status = IoUtils.checkFileExists(parent, options);
            if (status == null) {
                throw new AccessDeniedException("Receive directory parent (" + parent + ") existence status cannot be determined for " + path);
            }

            if (status && Files.isDirectory(parent, options)) {
                file = path;
            }
        }

        if (file == null) {
            throw new IOException("Cannot write to " + path);
        }

        status = IoUtils.checkFileExists(file, options);
        if (status == null) {
            throw new AccessDeniedException("Receive directory file existence status cannot be determined: " + file);
        }

        if (!(status.booleanValue() && Files.isDirectory(file, options))) {
            Files.createDirectory(file);
        }

        if (preserve) {
            updateFileProperties(file, perms, time);
        }

        ack();

        time = null;
        listener.startFolderEvent(FileOperation.RECEIVE, path, perms);
        try {
            for (;;) {
                header = readLine();
                if (log.isDebugEnabled()) {
                    log.debug("receiveDir({})[{}] Received header: {}", this, file, header);
                }
                if (header.startsWith("C")) {
                    receiveFile(header, file, time, preserve, bufferSize);
                    time = null;
                } else if (header.startsWith("D")) {
                    receiveDir(header, file, time, preserve, bufferSize);
                    time = null;
                } else if (header.equals("E")) {
                    ack();
                    break;
                } else if (header.startsWith("T")) {
                    time = ScpTimestamp.parseTime(header);
                    ack();
                } else {
                    throw new IOException("Unexpected message: '" + header + "'");
                }
            }
        } catch (IOException | RuntimeException e) {
            listener.endFolderEvent(FileOperation.RECEIVE, path, perms, e);
            throw e;
        }
        listener.endFolderEvent(FileOperation.RECEIVE, path, perms, null);
    }

    public void receiveFile(String header, Path local, ScpTimestamp time, boolean preserve, int bufferSize) throws IOException {
        Path path = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        if (log.isDebugEnabled()) {
            log.debug("receiveFile({})[{}] Receiving file {} - preserve={}, time={}, buffer-size={}",
                      this, header, path, preserve, time, bufferSize);
        }

        receiveStream(header, new LocalFileScpTargetStreamResolver(path, opener), time, preserve, bufferSize);
    }

    public void receiveStream(String header, ScpTargetStreamResolver resolver, ScpTimestamp time, boolean preserve, int bufferSize) throws IOException {
        if (!header.startsWith("C")) {
            throw new IOException("receiveStream(" + resolver + ") Expected a C message but got '" + header + "'");
        }

        if (bufferSize < MIN_RECEIVE_BUFFER_SIZE) {
            throw new IOException("receiveStream(" + resolver + ") buffer size (" + bufferSize + ") below minimum (" + MIN_RECEIVE_BUFFER_SIZE + ")");
        }

        Set<PosixFilePermission> perms = parseOctalPermissions(header.substring(1, 5));
        final long length = Long.parseLong(header.substring(6, header.indexOf(' ', 6)));
        String name = header.substring(header.indexOf(' ', 6) + 1);
        if (length < 0L) { // TODO consider throwing an exception...
            log.warn("receiveStream({})[{}] bad length in header: {}", this, resolver, header);
        }

        // if file size is less than buffer size allocate only expected file size
        int bufSize;
        if (length == 0L) {
            if (log.isDebugEnabled()) {
                log.debug("receiveStream({})[{}] zero file size (perhaps special file) using copy buffer size={}",
                          this, resolver, MIN_RECEIVE_BUFFER_SIZE);
            }
            bufSize = MIN_RECEIVE_BUFFER_SIZE;
        } else {
            bufSize = (int) Math.min(length, bufferSize);
        }

        if (bufSize < 0) { // TODO consider throwing an exception
            log.warn("receiveStream({})[{}] bad buffer size ({}) using default ({})",
                     this, resolver, bufSize, MIN_RECEIVE_BUFFER_SIZE);
            bufSize = MIN_RECEIVE_BUFFER_SIZE;
        }

        try (
                InputStream is = new LimitInputStream(this.in, length);
                OutputStream os = resolver.resolveTargetStream(getSession(), name, length, perms)
        ) {
            ack();

            Path file = resolver.getEventListenerFilePath();
            listener.startFileEvent(FileOperation.RECEIVE, file, length, perms);
            try {
                IoUtils.copy(is, os, bufSize);
            } catch (IOException | RuntimeException e) {
                listener.endFileEvent(FileOperation.RECEIVE, file, length, perms, e);
                throw e;
            }
            listener.endFileEvent(FileOperation.RECEIVE, file, length, perms, null);
        }

        resolver.postProcessReceivedData(name, preserve, perms, time);

        ack();

        int replyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("receiveStream({})[{}] ack reply code={}", this, resolver, replyCode);
        }
        validateAckReplyCode("receiveStream", resolver, replyCode, false);
    }

    protected void updateFileProperties(Path file, Set<PosixFilePermission> perms, ScpTimestamp time) throws IOException {
        if (log.isTraceEnabled()) {
            log.trace("updateFileProperties({}) {} permissions={}, time={}", this, file, perms, time);
        }
        IoUtils.setPermissions(file, perms);

        if (time != null) {
            BasicFileAttributeView view = Files.getFileAttributeView(file, BasicFileAttributeView.class);
            FileTime lastModified = FileTime.from(time.getLastModifiedTime(), TimeUnit.MILLISECONDS);
            FileTime lastAccess = FileTime.from(time.getLastAccessTime(), TimeUnit.MILLISECONDS);
            if (log.isTraceEnabled()) {
                log.trace("updateFileProperties({}) {} last-modified={}, last-access={}", this, file, lastModified, lastAccess);
            }
            view.setTimes(lastModified, lastAccess, null);
        }
    }

    public String readLine() throws IOException {
        return readLine(false);
    }

    public String readLine(boolean canEof) throws IOException {
        try (ByteArrayOutputStream baos = new ByteArrayOutputStream(Byte.MAX_VALUE)) {
            for (;;) {
                int c = in.read();
                if (c == '\n') {
                    return baos.toString(StandardCharsets.UTF_8.name());
                } else if (c == -1) {
                    if (!canEof) {
                        throw new EOFException("EOF while await end of line");
                    }
                    return null;
                } else {
                    baos.write(c);
                }
            }
        }
    }

    public void send(Collection<String> paths, boolean recursive, boolean preserve, int bufferSize) throws IOException {
        int readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("send({}) ready code={}", paths, readyCode);
        }
        validateOperationReadyCode("send", "Paths", readyCode, false);

        LinkOption[] options = IoUtils.getLinkOptions(false);
        for (String pattern : paths) {
            pattern = pattern.replace('/', File.separatorChar);

            int idx = pattern.indexOf('*'); // check if wildcard used
            if (idx >= 0) {
                String basedir = "";
                String fixedPart = pattern.substring(0, idx);
                int lastSep = fixedPart.lastIndexOf(File.separatorChar);
                if (lastSep >= 0) {
                    basedir = pattern.substring(0, lastSep);
                    pattern = pattern.substring(lastSep + 1);
                }

                String[] included = new DirectoryScanner(basedir, pattern).scan();
                for (String path : included) {
                    Path file = resolveLocalPath(basedir, path);
                    if (Files.isRegularFile(file, options)) {
                        sendFile(file, preserve, bufferSize);
                    } else if (Files.isDirectory(file, options)) {
                        if (!recursive) {
                            if (log.isDebugEnabled()) {
                                log.debug("send({}) {}: not a regular file", this, path);
                            }
                            sendWarning(path.replace(File.separatorChar, '/') + " not a regular file");
                        } else {
                            sendDir(file, preserve, bufferSize);
                        }
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("send({}) {}: unknown file type", this, path);
                        }
                        sendWarning(path.replace(File.separatorChar, '/') + " unknown file type");
                    }
                }
            } else {
                send(resolveLocalPath(pattern), recursive, preserve, bufferSize, options);
            }
        }
    }

    public void sendPaths(Collection<? extends Path> paths, boolean recursive, boolean preserve, int bufferSize) throws IOException {
        int readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("sendPaths({}) ready code={}", paths, readyCode);
        }
        validateOperationReadyCode("sendPaths", "Paths", readyCode, false);

        LinkOption[] options = IoUtils.getLinkOptions(false);
        for (Path file : paths) {
            send(file, recursive, preserve, bufferSize, options);
        }
    }

    protected void send(Path local, boolean recursive, boolean preserve, int bufferSize, LinkOption... options) throws IOException {
        Path file = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        Boolean status = IoUtils.checkFileExists(file, options);
        if (status == null) {
            throw new AccessDeniedException("Send file existence status cannot be determined: " + file);
        }
        if (!status) {
            throw new IOException(file + ": no such file or directory");
        }

        if (Files.isRegularFile(file, options)) {
            sendFile(file, preserve, bufferSize);
        } else if (Files.isDirectory(file, options)) {
            if (!recursive) {
                throw new IOException(file + " not a regular file");
            } else {
                sendDir(file, preserve, bufferSize);
            }
        } else {
            throw new IOException(file + ": unknown file type");
        }
    }

    public Path resolveLocalPath(String basedir, String subpath) throws IOException {
        if (GenericUtils.isEmpty(basedir)) {
            return resolveLocalPath(subpath);
        } else {
            return resolveLocalPath(basedir + File.separator + subpath);
        }
    }

    /**
     * @param commandPath The command path using the <U>local</U> file separator
     * @return The resolved absolute and normalized local path {@link Path}
     * @throws IOException If failed to resolve the path
     * @throws InvalidPathException If invalid local path value
     */
    public Path resolveLocalPath(String commandPath) throws IOException, InvalidPathException {
        String path = SelectorUtils.translateToLocalFileSystemPath(commandPath, File.separatorChar, fileSystem);
        Path lcl = fileSystem.getPath(path);
        Path abs = lcl.isAbsolute() ? lcl : lcl.toAbsolutePath();
        Path p = abs.normalize();
        if (log.isTraceEnabled()) {
            log.trace("resolveLocalPath({}) {}: {}", this, commandPath, p);
        }

        return p;
    }

    public void sendFile(Path local, boolean preserve, int bufferSize) throws IOException {
        Path path = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        if (log.isDebugEnabled()) {
            log.debug("sendFile({})[preserve={},buffer-size={}] Sending file {}", this, preserve, bufferSize, path);
        }

        sendStream(new LocalFileScpSourceStreamResolver(path, opener), preserve, bufferSize);
    }

    public void sendStream(ScpSourceStreamResolver resolver, boolean preserve, int bufferSize) throws IOException {
        if (bufferSize < MIN_SEND_BUFFER_SIZE) {
            throw new IOException("sendStream(" + resolver + ") buffer size (" + bufferSize + ") below minimum (" + MIN_SEND_BUFFER_SIZE + ")");
        }

        long fileSize = resolver.getSize();
        // if file size is less than buffer size allocate only expected file size
        int bufSize;
        if (fileSize <= 0L) {
            if (log.isDebugEnabled()) {
                log.debug("sendStream({})[{}] unknown file size ({}) perhaps special file - using copy buffer size={}",
                          this, resolver, fileSize, MIN_SEND_BUFFER_SIZE);
            }
            bufSize = MIN_SEND_BUFFER_SIZE;
        } else {
            bufSize = (int) Math.min(fileSize, bufferSize);
        }

        if (bufSize < 0) { // TODO consider throwing an exception
            log.warn("sendStream({})[{}] bad buffer size ({}) using default ({})",
                     this, resolver, bufSize, MIN_SEND_BUFFER_SIZE);
            bufSize = MIN_SEND_BUFFER_SIZE;
        }

        ScpTimestamp time = resolver.getTimestamp();
        if (preserve && (time != null)) {
            String cmd = "T" + TimeUnit.MILLISECONDS.toSeconds(time.getLastModifiedTime())
                    + " " + "0" + " " + TimeUnit.MILLISECONDS.toSeconds(time.getLastAccessTime())
                    + " " + "0";
            if (log.isDebugEnabled()) {
                log.debug("sendStream({})[{}] send timestamp={} command: {}", this, resolver, time, cmd);
            }
            out.write(cmd.getBytes(StandardCharsets.UTF_8));
            out.write('\n');
            out.flush();

            int readyCode = readAck(false);
            if (log.isDebugEnabled()) {
                log.debug("sendStream({})[{}] command='{}' ready code={}", this, resolver, cmd, readyCode);
            }
            validateAckReplyCode(cmd, resolver, readyCode, false);
        }

        Set<PosixFilePermission> perms = EnumSet.copyOf(resolver.getPermissions());
        String octalPerms = preserve ? getOctalPermissions(perms) : "0644";
        String fileName = resolver.getFileName();
        String cmd = "C" + octalPerms + " " + fileSize + " " + fileName;
        if (log.isDebugEnabled()) {
            log.debug("sendStream({})[{}] send 'C' command: {}", this, resolver, cmd);
        }
        out.write(cmd.getBytes(StandardCharsets.UTF_8));
        out.write('\n');
        out.flush();

        int readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("sendStream({})[{}] command='{}' ready code={}",
                      this, resolver, cmd.substring(0, cmd.length() - 1), readyCode);
        }
        validateAckReplyCode(cmd, resolver, readyCode, false);

        try (InputStream in = resolver.resolveSourceStream(getSession())) {
            Path path = resolver.getEventListenerFilePath();
            listener.startFileEvent(FileOperation.SEND, path, fileSize, perms);
            try {
                IoUtils.copy(in, out, bufSize);
            } catch (IOException | RuntimeException e) {
                listener.endFileEvent(FileOperation.SEND, path, fileSize, perms, e);
                throw e;
            }
            listener.endFileEvent(FileOperation.SEND, path, fileSize, perms, null);
        }
        ack();

        readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("sendStream({})[{}] command='{}' reply code={}", this, resolver, cmd, readyCode);
        }
        validateAckReplyCode("sendStream", resolver, readyCode, false);
    }

    protected void validateOperationReadyCode(String command, Object location, int readyCode, boolean eofAllowed) throws IOException {
        validateCommandStatusCode(command, location, readyCode, eofAllowed);
    }

    protected void validateAckReplyCode(String command, Object location, int replyCode, boolean eofAllowed) throws IOException {
        validateCommandStatusCode(command, location, replyCode, eofAllowed);
    }

    protected void validateCommandStatusCode(String command, Object location, int statusCode, boolean eofAllowed) throws IOException {
        switch (statusCode) {
            case -1:
                if (!eofAllowed) {
                    throw new EOFException("Unexpected EOF for command='" + command + "' on " + location);
                }
                break;
            case OK:
                break;
            case WARNING:
                break;
            default:
                throw new ScpException("Bad reply code (" + statusCode + ") for command='" + command + "' on " + location, Integer.valueOf(statusCode));
        }
    }

    public void sendDir(Path local, boolean preserve, int bufferSize) throws IOException {
        Path path = ValidateUtils.checkNotNull(local, "No local path").normalize().toAbsolutePath();
        if (log.isDebugEnabled()) {
            log.debug("sendDir({}) Sending directory {} - preserve={}, buffer-size={}",
                      this, path, preserve, bufferSize);
        }

        BasicFileAttributes basic = Files.getFileAttributeView(path, BasicFileAttributeView.class).readAttributes();
        if (preserve) {
            FileTime lastModified = basic.lastModifiedTime();
            FileTime lastAccess = basic.lastAccessTime();
            String cmd = "T" + lastModified.to(TimeUnit.SECONDS) + " "
                    + "0" + " " + lastAccess.to(TimeUnit.SECONDS) + " "
                    + "0";
            if (log.isDebugEnabled()) {
                log.debug("sendDir({})[{}] send last-modified={}, last-access={} command: {}",
                          this, path, lastModified,  lastAccess, cmd);
            }

            out.write(cmd.getBytes(StandardCharsets.UTF_8));
            out.write('\n');
            out.flush();

            int readyCode = readAck(false);
            if (log.isDebugEnabled()) {
                if (log.isDebugEnabled()) {
                    log.debug("sendDir({})[{}] command='{}' ready code={}", this, path, cmd, readyCode);
                }
            }
            validateAckReplyCode(cmd, path, readyCode, false);
        }

        LinkOption[] options = IoUtils.getLinkOptions(false);
        Set<PosixFilePermission> perms = IoUtils.getPermissions(path, options);
        String cmd = "D" + (preserve ? getOctalPermissions(perms) : "0755") + " "
                + "0" + " " + path.getFileName().toString();
        if (log.isDebugEnabled()) {
            log.debug("sendDir({})[{}] send 'D' command: {}", this, path, cmd);
        }
        out.write(cmd.getBytes(StandardCharsets.UTF_8));
        out.write('\n');
        out.flush();

        int readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("sendDir({})[{}] command='{}' ready code={}",
                      this, path, cmd.substring(0, cmd.length() - 1), readyCode);
        }
        validateAckReplyCode(cmd, path, readyCode, false);

        try (DirectoryStream<Path> children = Files.newDirectoryStream(path)) {
            listener.startFolderEvent(FileOperation.SEND, path, perms);

            try {
                for (Path child : children) {
                    if (Files.isRegularFile(child, options)) {
                        sendFile(child, preserve, bufferSize);
                    } else if (Files.isDirectory(child, options)) {
                        sendDir(child, preserve, bufferSize);
                    }
                }
            } catch (IOException | RuntimeException e) {
                listener.endFolderEvent(FileOperation.SEND, path, perms, e);
                throw e;
            }

            listener.endFolderEvent(FileOperation.SEND, path, perms, null);
        }

        if (log.isDebugEnabled()) {
            log.debug("sendDir({})[{}] send 'E' command", this, path);
        }
        out.write("E\n".getBytes(StandardCharsets.UTF_8));
        out.flush();


        readyCode = readAck(false);
        if (log.isDebugEnabled()) {
            log.debug("sendDir({})[{}] 'E' command reply code=", this, path, readyCode);
        }
        validateAckReplyCode("E", path, readyCode, false);
    }

    public static String getOctalPermissions(Path path, LinkOption... options) throws IOException {
        return getOctalPermissions(IoUtils.getPermissions(path, options));
    }

    public static String getOctalPermissions(Collection<PosixFilePermission> perms) {
        int pf = 0;

        for (PosixFilePermission p : perms) {
            switch (p) {
                case OWNER_READ:
                    pf |= S_IRUSR;
                    break;
                case OWNER_WRITE:
                    pf |= S_IWUSR;
                    break;
                case OWNER_EXECUTE:
                    pf |= S_IXUSR;
                    break;
                case GROUP_READ:
                    pf |= S_IRGRP;
                    break;
                case GROUP_WRITE:
                    pf |= S_IWGRP;
                    break;
                case GROUP_EXECUTE:
                    pf |= S_IXGRP;
                    break;
                case OTHERS_READ:
                    pf |= S_IROTH;
                    break;
                case OTHERS_WRITE:
                    pf |= S_IWOTH;
                    break;
                case OTHERS_EXECUTE:
                    pf |= S_IXOTH;
                    break;
                default:    // ignored
            }
        }

        return String.format("%04o", pf);
    }

    public static Set<PosixFilePermission> setOctalPermissions(Path path, String str) throws IOException {
        Set<PosixFilePermission> perms = parseOctalPermissions(str);
        IoUtils.setPermissions(path, perms);
        return perms;
    }

    public static Set<PosixFilePermission> parseOctalPermissions(String str) {
        int perms = Integer.parseInt(str, 8);
        Set<PosixFilePermission> p = EnumSet.noneOf(PosixFilePermission.class);
        if ((perms & S_IRUSR) != 0) {
            p.add(PosixFilePermission.OWNER_READ);
        }
        if ((perms & S_IWUSR) != 0) {
            p.add(PosixFilePermission.OWNER_WRITE);
        }
        if ((perms & S_IXUSR) != 0) {
            p.add(PosixFilePermission.OWNER_EXECUTE);
        }
        if ((perms & S_IRGRP) != 0) {
            p.add(PosixFilePermission.GROUP_READ);
        }
        if ((perms & S_IWGRP) != 0) {
            p.add(PosixFilePermission.GROUP_WRITE);
        }
        if ((perms & S_IXGRP) != 0) {
            p.add(PosixFilePermission.GROUP_EXECUTE);
        }
        if ((perms & S_IROTH) != 0) {
            p.add(PosixFilePermission.OTHERS_READ);
        }
        if ((perms & S_IWOTH) != 0) {
            p.add(PosixFilePermission.OTHERS_WRITE);
        }
        if ((perms & S_IXOTH) != 0) {
            p.add(PosixFilePermission.OTHERS_EXECUTE);
        }

        return p;
    }

    protected void sendWarning(String message) throws IOException {
        sendResponseMessage(WARNING, message);
    }

    protected void sendError(String message) throws IOException {
        sendResponseMessage(ERROR, message);
    }

    protected void sendResponseMessage(int level, String message) throws IOException {
        sendResponseMessage(out, level, message);
    }

    public static <O extends OutputStream> O sendWarning(O out, String message) throws IOException {
        return sendResponseMessage(out, WARNING, message);
    }

    public static <O extends OutputStream> O sendError(O out, String message) throws IOException {
        return sendResponseMessage(out, ERROR, message);
    }

    public static <O extends OutputStream> O sendResponseMessage(O out, int level, String message) throws IOException {
        out.write(level);
        out.write(message.getBytes(StandardCharsets.UTF_8));
        out.write('\n');
        out.flush();
        return out;
    }

    public static String getExitStatusName(Integer exitStatus) {
        if (exitStatus == null) {
            return "null";
        }

        switch (exitStatus.intValue()) {
            case OK:
                return "OK";
            case WARNING:
                return "WARNING";
            case ERROR:
                return "ERROR";
            default:
                return exitStatus.toString();
        }
    }

    public void ack() throws IOException {
        out.write(0);
        out.flush();
    }

    public int readAck(boolean canEof) throws IOException {
        int c = in.read();
        switch (c) {
            case -1:
                if (log.isDebugEnabled()) {
                    log.debug("readAck({})[EOF={}] received EOF", this, canEof);
                }
                if (!canEof) {
                    throw new EOFException("readAck - EOF before ACK");
                }
                break;
            case OK:
                if (log.isDebugEnabled()) {
                    log.debug("readAck({})[EOF={}] read OK", this, canEof);
                }
                break;
            case WARNING: {
                if (log.isDebugEnabled()) {
                    log.debug("readAck({})[EOF={}] read warning message", this, canEof);
                }

                String line = readLine();
                log.warn("readAck({})[EOF={}] - Received warning: {}", this, canEof, line);
                break;
            }
            case ERROR: {
                if (log.isDebugEnabled()) {
                    log.debug("readAck({})[EOF={}] read error message", this, canEof);
                }
                String line = readLine();
                if (log.isDebugEnabled()) {
                    log.debug("readAck({})[EOF={}] received error: {}", this, canEof, line);
                }
                throw new ScpException("Received nack: " + line, Integer.valueOf(c));
            }
            default:
                break;
        }
        return c;
    }

    @Override
    public String toString() {
        return getClass().getSimpleName() + "[" + getSession() + "]";
    }
}
