/*
    Copyright (c) 2005-2024 Leisenfels GmbH. All rights reserved.
    Use is subject to license terms.
*/

package com.lf.vfslib.test;

import com.lf.vfslib.net.VFSUtils;
import org.apache.commons.vfs2.FileObject;
import org.apache.commons.vfs2.FileSystemException;
import org.apache.commons.vfs2.FileSystemOptions;
import org.apache.commons.vfs2.VFS;
import org.apache.commons.vfs2.impl.DefaultFileSystemManager;
import org.apache.commons.vfs2.provider.ftp.FtpFileSystemConfigBuilder;
import org.apache.commons.vfs2.provider.sftp.SftpFileSystemConfigBuilder;

import javax.swing.*;
import java.io.InputStream;
import java.io.OutputStream;


/**
 * Example class showing how an anonymous FTP file is copied over to a configurable SFTP server.
 * <p>
 *
 * @author Axel Schwolow
 * @since 1.6
 */
public class ExampleVFS {


    /**
     * Constructor method.
     * <p>
     *
     * @param host     SFTP server address
     * @param username SFTP username (optional, per dialog)
     * @param password SFTP user password (optional, per dialog)
     * @param port     SFTP port (optional, default: 22)
     * @param path     SFTP subdirectory (optional)
     * @throws FileSystemException Error indication
     * @since 1.6
     */
    public ExampleVFS(String host, String username, String password, String port, String path) throws FileSystemException {

        System.out.println("Configuring VFS:");
        System.out.println("    host               " + host);
        System.out.println("    username           " + (username != null ? username : "(per dialog)"));
        System.out.println("    password           " + (password != null ? "***" : "(per dialog)"));
        System.out.println("    port               " + (port != null ? port : "(using default)"));
        System.out.println("    path               " + (path != null ? path : "(n/a)"));

        if (username == null) {
            username = JOptionPane.showInputDialog("Please enter the SFTP user name");
            System.out.println("The SFTP user name is: " + username);
        }
        if (password == null) {
            password = JOptionPane.showInputDialog("Please enter the SFTP password");
            System.out.println("The SFTP password is set");
        }

        // We use the default file system manager here
        DefaultFileSystemManager fsmanager = (DefaultFileSystemManager) VFS.getManager();

        // Connect to anonymous FTP server, copy file over to SFTP server
        String ftpuri = "ftp://ftp.gnu.org:21/gnu/ProgramIndex";
        String sftpuri = "sftp://" + username + ":" + password + "@" + host;
        if (port != null) sftpuri += ":" + port;
        if (path != null) sftpuri += path;
        sftpuri += "/README";
        // e.g. "sftp://scott:tiger@mycompany.com:22/mydir/README"

        // Configure FTP
        FileSystemOptions ftpoptions = new FileSystemOptions();
        FtpFileSystemConfigBuilder ftpbuilder = FtpFileSystemConfigBuilder.getInstance();
        ftpbuilder.setPassiveMode(ftpoptions, true);

        // SFTP needs a little configuring, too
        FileSystemOptions sftpoptions = new FileSystemOptions();
        SftpFileSystemConfigBuilder sftpbuilder = SftpFileSystemConfigBuilder.getInstance();
        sftpbuilder.setStrictHostKeyChecking(sftpoptions, "no");  // Loose checking
        sftpbuilder.setUserDirIsRoot(sftpoptions, false);         // "/" is root

        boolean success = false;
        try {
            // Open input stream for FTP file (read from)
            FileObject ftpobj = fsmanager.resolveFile(ftpuri, ftpoptions);  // Throws
            InputStream istream = ftpobj.getContent().getInputStream();
            System.out.println("Successfully connected to FTP server " + ftpuri);

            // Open output stream for SFTP file (write into)
            FileObject sftpobj = fsmanager.resolveFile(sftpuri, sftpoptions);  // Throws
            System.out.println("Copying FTP file " + ftpuri + " over to SFTP file " + VFSUtils.getDisplayURIObfuscated(sftpobj, null));
            OutputStream ostream = sftpobj.getContent().getOutputStream();
            System.out.println("    Successfully connected to SFTP server");

            // Copy bytes
            int len;
            byte[] buffer = new byte[1024];
            while ((len = istream.read(buffer)) != -1) {
                ostream.write(buffer, 0, len);
            }
            ostream.flush();
            ostream.close();
            istream.close();

            long size = sftpobj.getContent().getSize();
            success = sftpobj.exists() && size == ftpobj.getContent().getSize();
            System.out.println(success ? "    Successful, copied " + size + " bytes" : "    Failed");
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (!success) {
            System.err.println("Sorry, could not upload file, exiting");
        }
    }

    /**
     * Functionality for testing and debugging.
     * <p>
     * Supported arguments:
     * <code>
     * -host [value]               SFTP server address
     * -username [value]           SFTP username (optional, per dialog)
     * -password [value]           SFTP user password (optional, per dialog)
     * -port [value]               SFTP port (optional, default: 22)
     * -path [value]               SFTP subdirectory (optional)
     * </code>
     * <p>
     *
     * @param args Array of strings with console arguments
     * @since 1.6
     */
    public static void main(String[] args) {

        String host = null, username = null, password = null, port = null, path = null;

        try {
            // Disable annoying VFS log messages like:
            // 20.09.2013 13:48:31 org.apache.commons.vfs2.VfsLog info
            // INFO: Using "C:\DOCUME~1\User1\LOCALS~1\Temp\vfs_cache" as temporary files store.
            System.setProperty("org.apache.commons.logging.Log", "org.apache.commons.logging.impl.NoOpLog");
            System.out.println();

            // Parse arguments
            for (int i = 0; i < args.length; i++) {
                if (args[i].equals("-host") && (i + 1) < args.length) host = args[++i];
                else if (args[i].equals("-username") && (i + 1) < args.length) username = args[++i];
                else if (args[i].equals("-password") && (i + 1) < args.length) password = args[++i];
                else if (args[i].equals("-port") && (i + 1) < args.length) port = args[++i];
                else if (args[i].equals("-path") && (i + 1) < args.length) path = args[++i];
            }

            new ExampleVFS(host, username, password, port, path);
            System.exit(0);
        } catch (Exception exc) {
            try {
                Thread.sleep(1000);
            } catch (Exception ignored) {
            }
            exc.printStackTrace();
        }
        System.exit(1);
    }
}
