package io.renren.common.utils;

import com.jcraft.jsch.*;
import org.apache.commons.net.ftp.FTPClient;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Properties;
import java.util.Vector;


public class FTPUtils {

    private static String host;

    private static String username;

    private static String password;

    private static String basePath;

    private static int port;

    private static ChannelSftp sftp;

    private static Channel channel;

    private static boolean key_needed;

    private static String key_location;

    public FTPUtils(String host,String username,String password,String basePath,int port,boolean key_needed,String key_location){
        FTPUtils.host=host;
        FTPUtils.username=username;
        FTPUtils.password=password;
        FTPUtils.basePath=basePath;
        FTPUtils.port=port;
        FTPUtils.key_needed=key_needed;
        FTPUtils.key_location=key_location;
        initFTPUtil();
    }

    public void initFTPUtil(){
        FTPClient ftp=new FTPClient();
        try {
            JSch jsch=new JSch();
            System.out.println("是否需要秘钥"+key_needed);
            if(key_needed){
                jsch.addIdentity(key_location);
            }
            //获取sshSession  账号-ip-端口
            Session sshSession=jsch.getSession(username,host,port);
            //添加密码
            sshSession.setPassword(password);
            Properties sshConfig=new Properties();

            //严格主机密钥检查
            sshConfig.put("StrictHostKeyChecking","no");
            sshSession.setConfig(sshConfig);

            //开启sshSession连接
            sshSession.connect();
            //获取sftp通道
            channel=sshSession.openChannel("sftp");
            channel.connect();

            sftp=(ChannelSftp) channel;

            ftp.enterLocalPassiveMode();
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }

    /**
     * Description: 在服务器创建文件夹
     * @param filePath 要创建的文件夹名，创建位置在basePath下
     * @return 成功返回true，否则false
     */
    public static boolean mkdir(String filePath){
        boolean result=false;
        try {
            sftp.cd("/");
            sftp.cd(basePath);
            sftp.mkdir(filePath);

            return true;
        } catch (SftpException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * Description: 向FTP服务器上传文件
     * @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
     * @param filename 上传到FTP服务器上的文件名
     * @param input 输入流
     * @return 成功返回true，否则false
     */
    public static boolean uploadFile(String filePath,String filename, InputStream input){
        boolean result=false;
        try {
            sftp.cd("/");
            sftp.cd(basePath);
            sftp.cd(filePath);
            sftp.put(input,filename);

            return true;
        } catch (SftpException e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * Description: 从FTP服务器下载文件
     * @param filePath FTP服务器文件存放路径。文件的路径为basePath+filePath
     * @return 成功返回true，否则false
     */
    public static InputStream downloadFile(String filePath){
        try {
            InputStream inputStream=sftp.get(filePath);
            return inputStream;
        } catch (SftpException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Description: 判断目录是否存在
     * @param filePath
     * @return
     */
    public static boolean isDirExist(String filePath){
        boolean isDirExistFlag=false;
        try {
            SftpATTRS sftpATTRS=sftp.lstat(basePath+"/"+filePath);
            isDirExistFlag=true;
            return sftpATTRS.isDir();
        } catch (Exception e) {
            if (e.getMessage().toLowerCase().equals("no such file")) {
                isDirExistFlag = false;
            }
        }
        return isDirExistFlag;
    }

    /**
     * Description: 执行命令
     * @param cmd 要执行的命令
     * @return 成功返回true，否则false
     */
    public static String execCmd(String cmd) throws JSchException {
        JSch jSch = new JSch();

        System.out.println("是否需要秘钥"+key_needed);
        if(key_needed){
            jSch.addIdentity(key_location);
        }
        Session session = null;
        ChannelExec channelExec = null;
        BufferedReader inputStreamReader = null;
        BufferedReader errInputStreamReader = null;
        StringBuilder runLog = new StringBuilder("");
        StringBuilder errLog = new StringBuilder("");
        try {
            // 1. 获取 ssh session
            session = jSch.getSession(username, host, port);
            session.setPassword(password);
            session.setTimeout(60 * 60 * 1000);
            session.setConfig("StrictHostKeyChecking", "no");
            session.connect();  // 获取到 ssh session

            // 2. 通过 exec 方式执行 shell 命令
            channelExec = (ChannelExec) session.openChannel("exec");
            channelExec.setCommand(cmd);
            channelExec.connect();  // 执行命令

            // 3. 获取标准输入流
            inputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getInputStream()));
            // 4. 获取标准错误输入流
            errInputStreamReader = new BufferedReader(new InputStreamReader(channelExec.getErrStream()));

            // 5. 记录命令执行 log
            String line = null;
            while ((line = inputStreamReader.readLine()) != null) {
                runLog.append(line).append("\n");
            }

            // 6. 记录命令执行错误 log
            String errLine = null;
            while ((errLine = errInputStreamReader.readLine()) != null) {
                errLog.append(errLine).append("\n");
            }

            // 7. 输出 shell 命令执行日志
            System.out.println("exitStatus=" + channelExec.getExitStatus() + ", openChannel.isClosed="
                    + channelExec.isClosed());
            System.out.println("命令执行完成，执行日志如下:");
            System.out.println(runLog.toString());
            System.out.println("命令执行完成，执行错误日志如下:");
            System.out.println(errLog.toString());
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (inputStreamReader != null) {
                    inputStreamReader.close();
                }
                if (errInputStreamReader != null) {
                    errInputStreamReader.close();
                }

                if (channelExec != null) {
                    channelExec.disconnect();
                }
                if (session != null) {
                    session.disconnect();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return runLog.append(errLog).toString();

    }

    /**
     * Description: 显示目标地址下的文件 地址为basePath+filePath
     * @param filePath
     * @return
     */
    public static Vector<ChannelSftp.LsEntry> showFiles(String filePath){
        Vector vector=new Vector();
        try {
            vector=sftp.ls(basePath+"/"+filePath);
        } catch (SftpException e) {
            e.printStackTrace();
        }
        return vector;
    }

}
