/*
 * 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.sftp;

import java.io.IOException;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.util.Collection;
import java.util.Objects;

import org.apache.commons.lang3.time.DurationUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.commons.vfs2.Capability;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.provider.AbstractFileName;
import org.apache.commons.vfs2.provider.AbstractFileSystem;
import org.apache.commons.vfs2.provider.GenericFileName;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * Represents the files on an SFTP server.
 */
public class SftpFileSystem extends AbstractFileSystem {

    private static final Log LOG = LogFactory.getLog(SftpFileSystem.class);

    private static final int UNIDENTIFED = -1;

    private static final int SLEEP_MILLIS = 100;

    private static final int EXEC_BUFFER_SIZE = 128;

    private static final long LAST_MOD_TIME_ACCURACY = 1000L;

    /**
     * Session; never null.
     * <p>
     * DCL pattern requires that the ivar be volatile.
     * </p>
     */
    private volatile Session session;

    private volatile ChannelSftp idleChannel;

    private final Duration connectTimeout;

    /**
     * Cache for the user ID (-1 when not set)
     * <p>
     * DCL pattern requires that the ivar be volatile.
     * </p>
     */
    private volatile int uid = UNIDENTIFED;

    /**
     * Cache for the user groups ids (null when not set)
     * <p>
     * DCL pattern requires that the ivar be volatile.
     * </p>
     */
    private volatile int[] groupsIds;

    /**
     * Some SFTP-only servers disable the exec channel. When exec is disabled, things like getUId() will always fail.
     */
    private final boolean execDisabled;

    protected SftpFileSystem(final GenericFileName rootName, final Session session,
            final FileSystemOptions fileSystemOptions) {
        super(rootName, null, fileSystemOptions);
        this.session = Objects.requireNonNull(session, "session");
        this.connectTimeout = SftpFileSystemConfigBuilder.getInstance()
            .getConnectTimeout(fileSystemOptions);

        if (SftpFileSystemConfigBuilder.getInstance().isDisableDetectExecChannel(fileSystemOptions)) {
            this.execDisabled = true;
        } else {
            this.execDisabled = detectExecDisabled();
        }
    }

    @Override
    protected void doCloseCommunicationLink() {
        if (idleChannel != null) {
            synchronized (this) {
                if (idleChannel != null) {
                    idleChannel.disconnect();
                    idleChannel = null;
                }
            }
        }

        if (session != null) {
            session.disconnect();
        }
    }

    /**
     * Returns an SFTP channel to the server.
     *
     * @return new or reused channel, never null.
     * @throws FileSystemException if a session cannot be created.
     * @throws IOException         if an I/O error is detected.
     */
    protected ChannelSftp getChannel() throws IOException {
        try {
            // Use the pooled channel, or create a new one
            ChannelSftp channel = null;
            if (idleChannel != null) {
                synchronized (this) {
                    if (idleChannel != null) {
                        channel = idleChannel;
                        idleChannel = null;
                    }
                }
            }

            if (channel == null) {
                channel = (ChannelSftp) getSession().openChannel("sftp");
                channel.connect(DurationUtils.toMillisInt(connectTimeout));
                final Boolean userDirIsRoot = SftpFileSystemConfigBuilder.getInstance()
                        .getUserDirIsRoot(getFileSystemOptions());
                final String workingDirectory = getRootName().getPath();
                if (workingDirectory != null && (userDirIsRoot == null || !userDirIsRoot.booleanValue())) {
                    try {
                        channel.cd(workingDirectory);
                    } catch (final SftpException e) {
                        throw new FileSystemException("vfs.provider.sftp/change-work-directory.error", workingDirectory,
                                e);
                    }
                }
            }

            final String fileNameEncoding = SftpFileSystemConfigBuilder.getInstance()
                    .getFileNameEncoding(getFileSystemOptions());

            if (fileNameEncoding != null) {
                try {
                    channel.setFilenameEncoding(fileNameEncoding);
                } catch (final SftpException e) {
                    throw new FileSystemException("vfs.provider.sftp/filename-encoding.error", fileNameEncoding);
                }
            }
            return channel;
        } catch (final JSchException e) {
            throw new FileSystemException("vfs.provider.sftp/connect.error", getRootName(), e);
        }
    }

    /**
     * Ensures that the session link is established.
     *
     * @throws FileSystemException if a session cannot be created.
     */
    private Session getSession() throws FileSystemException {
        if (!this.session.isConnected()) {
            synchronized (this) {
                if (!this.session.isConnected()) {
                    doCloseCommunicationLink();
                    this.session = SftpFileProvider.createSession((GenericFileName) getRootName(),
                            getFileSystemOptions());
                }
            }
        }
        return this.session;
    }

    /**
     * Returns a channel to the pool.
     *
     * @param channelSftp the SFTP channel.
     */
    protected void putChannel(final ChannelSftp channelSftp) {
        if (idleChannel == null) {
            synchronized (this) {
                if (idleChannel == null) {
                    // put back the channel only if it is still connected
                    if (channelSftp.isConnected() && !channelSftp.isClosed()) {
                        idleChannel = channelSftp;
                    }
                } else {
                    channelSftp.disconnect();
                }
            }
        } else {
            channelSftp.disconnect();
        }
    }

    /**
     * Adds the capabilities of this file system.
     */
    @Override
    protected void addCapabilities(final Collection<Capability> caps) {
        caps.addAll(SftpFileProvider.capabilities);
    }

    /**
     * Creates a file object. This method is called only if the requested file is not cached.
     */
    @Override
    protected FileObject createFile(final AbstractFileName name) throws FileSystemException {
        return new SftpFileObject(name, this);
    }

    /**
     * Last modification time is only an int and in seconds, thus can be off by 999.
     *
     * @return 1000
     */
    @Override
    public double getLastModTimeAccuracy() {
        return LAST_MOD_TIME_ACCURACY;
    }

    /**
     * Gets the (numeric) group IDs.
     *
     * @return the (numeric) group IDs.
     * @throws JSchException If a problem occurs while retrieving the group IDs.
     * @throws IOException   if an I/O error is detected.
     * @since 2.1
     */
    public int[] getGroupsIds() throws JSchException, IOException {
        if (groupsIds == null) {
            synchronized (this) {
                // DCL pattern requires that the ivar be volatile.
                if (groupsIds == null) {
                    final StringBuilder output = new StringBuilder();
                    final int code = executeCommand("id -G", output);
                    if (code != 0) {
                        throw new JSchException(
                                "Could not get the groups id of the current user (error code: " + code + ")");
                    }
                    // Retrieve the different groups
                    final String[] groups = output.toString().trim().split("\\s+");

                    final int[] groupsIds = new int[groups.length];
                    for (int i = 0; i < groups.length; i++) {
                        groupsIds[i] = Integer.parseInt(groups[i]);
                    }
                    this.groupsIds = groupsIds;

                }
            }
        }
        return groupsIds;
    }

    /**
     * Gets the (numeric) group IDs.
     *
     * @return The numeric user ID
     * @throws JSchException If a problem occurs while retrieving the group ID.
     * @throws IOException   if an I/O error is detected.
     * @since 2.1
     */
    public int getUId() throws JSchException, IOException {
        if (uid == UNIDENTIFED) {
            synchronized (this) {
                if (uid == UNIDENTIFED) {
                    final StringBuilder output = new StringBuilder();
                    final int code = executeCommand("id -u", output);
                    if (code != 0) {
                        throw new FileSystemException(
                                "Could not get the user id of the current user (error code: " + code + ")");
                    }
                    final String uidString = output.toString().trim();
                    try {
                        uid = Integer.parseInt(uidString);
                    } catch (final NumberFormatException e) {
                        LOG.debug("Cannot convert UID to integer: '" + uidString + "'", e);
                    }
                }
            }
        }
        return uid;
    }

    /**
     * Executes a command and returns the (standard) output through a StringBuilder.
     *
     * @param command The command
     * @param output  The output
     * @return The exit code of the command
     * @throws JSchException       if a JSch error is detected.
     * @throws FileSystemException if a session cannot be created.
     * @throws IOException         if an I/O error is detected.
     */
    private int executeCommand(final String command, final StringBuilder output) throws JSchException, IOException {
        final ChannelExec channel = (ChannelExec) getSession().openChannel("exec");
        try {
            channel.setCommand(command);
            channel.setInputStream(null);
            try (final InputStreamReader stream = new InputStreamReader(channel.getInputStream(), StandardCharsets.UTF_8)) {
                channel.setErrStream(System.err, true);
                channel.connect(DurationUtils.toMillisInt(connectTimeout));

                // Read the stream
                final char[] buffer = new char[EXEC_BUFFER_SIZE];
                int read;
                while ((read = stream.read(buffer, 0, buffer.length)) >= 0) {
                    output.append(buffer, 0, read);
                }
            }

            // Wait until the command finishes (should not be long since we read the output stream)
            while (!channel.isClosed()) {
                try {
                    Thread.sleep(SLEEP_MILLIS);
                } catch (final Exception ee) {
                    // TODO: swallow exception, really?
                }
            }
        } finally {
            channel.disconnect();
        }
        return channel.getExitStatus();
    }

    /**
     * @return Whether the exec channel is disabled.
     * @see SftpFileSystem#execDisabled
     */
    public boolean isExecDisabled() {
        return execDisabled;
    }

    /**
     * Some SFTP-only servers disable the exec channel.
     *
     * Attempt to detect this by calling getUid.
     */
    private boolean detectExecDisabled() {
        try {
            return getUId() == UNIDENTIFED;
        } catch(final JSchException | IOException e) {
            LOG.debug("Cannot get UID, assuming no exec channel is present", e);
            return true;
        }
    }

}
