package org.apache.seatunnel.datasource.plugin.ftp;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.hadoop.fs.FSDataInputStream;
import org.apache.hadoop.fs.FileSystem;
import org.apache.hadoop.fs.ftp.FTPInputStream;
import org.apache.hadoop.net.NetUtils;

import java.io.IOException;
import java.io.InputStream;
import java.net.ConnectException;

public class FtpClientService {

    protected FileSystem.Statistics statistics;
    public static final String FS_FTP_HOST = "192.168.1.174";
    public static final Integer FS_FTP_HOST_PORT = 21;
    public static final String FS_FTP_USER_PREFIX = "ftp.";
    public static final String FS_FTP_PASSWORD_PREFIX = "ftp.";
    public static final String E_SAME_DIRECTORY_ONLY = "/ftp";

    private FTPClient connect() throws IOException {
        FTPClient client = null;
        String host = FS_FTP_HOST;
        int port = FS_FTP_HOST_PORT;
        String user = FS_FTP_USER_PREFIX;
        String password = FS_FTP_PASSWORD_PREFIX;
        client = new FTPClient();
        client.connect(host, port);
        int reply = client.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            throw NetUtils.wrapException(
                    host,
                    port,
                    NetUtils.UNKNOWN_HOST,
                    0,
                    new ConnectException("Server response " + reply));
        } else if (client.login(user, password)) {
            client.setFileTransferMode(FTP.BLOCK_TRANSFER_MODE);
            client.setFileType(FTP.BINARY_FILE_TYPE);
        } else {
            throw new IOException(
                    "Login failed on server - "
                            + host
                            + ", port - "
                            + port
                            + " as user '"
                            + user
                            + "'");
        }

        return client;
    }

    public FSDataInputStream open(String path) throws IOException {
        FTPClient client = connect();
        // Change to parent directory on the
        // server. Only then can we read the
        // file
        // on the server by opening up an InputStream. As a side effect the working
        // directory on the server is changed to the parent directory of the file.
        // The FTP client connection is closed when close() is called on the
        // FSDataInputStream.
        client.changeWorkingDirectory(path);
        InputStream is = client.retrieveFileStream(path);
        FSDataInputStream fis = new FSDataInputStream(new FTPInputStream(is, client, statistics));
        if (!FTPReply.isPositivePreliminary(client.getReplyCode())) {
            // The ftpClient is an inconsistent state. Must close the stream
            // which in turn will logout and disconnect from FTP server
            fis.close();
            throw new IOException("Unable to open file: " + path + ", Aborting");
        }
        return fis;
    }

}
