package shkd.utils;


import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Properties;
import java.util.Vector;

/**
 * <p>
 * ClassName: SFTPConnectUtil
 * </p>
 * <p>
 * Description: 连接SFTP
 * </p>
 */
public class SFTPConnectUtil {

    /**
     * 日志
     */
    private final static Log logger = LogFactory.getLog(SFTPConnectUtil.class);
    /**
     * 连接SFTP服务器
     *
     * @param host
     *            主机
     * @param port
     *            端口
     * @param username
     *            用户名
     * @param password
     *            密码
     * @return ChannelSftp
     */
    public static ChannelSftp connectSFTP(String host, int port,
                                          String username, String password) {
        // 声明ChannelSftp对象
        ChannelSftp sftp = null;
        try {
            // 创建JSch对象
            JSch jsch = new JSch();
            // 根据用户名,主机IP,端口获取一个Session对象
            Session sshSession = jsch.getSession(username, host, port);
            if (!isEmpty(password)) {
                sshSession.setPassword(password);
            }
            // 新建属性类
            Properties sshConfig = new Properties();
            /*
             * 连接新主机时,不进行公钥确认;
             * 在首次连接服务器时,会弹出公钥确认的提示。这会导致某些自动化任务,由于初次连接服务器而导致自动化任务中断。
             */
            sshConfig.put("StrictHostKeyChecking", "no");
            // 配置连接设置
            sshSession.setConfig(sshConfig);
            // 建立连接
            sshSession.connect();
            // 打开SFTP通道
            Channel channel = sshSession.openChannel("sftp");
            // 建立SFTP通道的连接
            channel.connect();
            // 强转ChannelSftp对象
            sftp = (ChannelSftp) channel;
        } catch (JSchException e) {
            logger.error("connectSFTP:" + e.toString());
            return null;
        }
        return sftp;
    }

    /**
     * 上传文件
     *
     * @param directory
     *            上传的目录
     * @param uploadFile
     *            要上传的文件
     * @param sftp
     * @return boolean
     */
    public static boolean uploadFile(String directory, File uploadFile,
                                     ChannelSftp sftp,String fileName) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            sftp.put(new FileInputStream(uploadFile), fileName);
        } catch (FileNotFoundException e) {
            logger.error("uploadFile -- FileNotFoundException:" + e.toString());
            return false;
        } catch (SftpException e) {
            logger.error("uploadFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }

    /**
     * 上传附件
     * @param directory
     * @param fileInputStream
     * @param fileName
     * @param sftp
     * @return
     */
    public static boolean uploadFile(String directory, FileInputStream fileInputStream,String fileName,
                                     ChannelSftp sftp) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            sftp.put(fileInputStream, fileName);
        } catch (SftpException e) {
            logger.error("uploadFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }
    /**
     * 下载文件
     *
     * @param directory
     *            下载目录
     * @param downloadFile
     *            下载的文件
     * @param saveFile
     *            存在本地的路径
     * @param sftp
     * @return boolean
     */
    public static boolean downloadFile(String directory, String downloadFile,
                                       File saveFile, ChannelSftp sftp) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            // 下载文件到指定路径
            sftp.get(downloadFile, new FileOutputStream(saveFile));
        } catch (FileNotFoundException e) {
            logger.error("downloadFile -- FileNotFoundException:"
                    + e.toString());
            return false;
        } catch (SftpException e) {
            logger.error("downloadFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }

    /**
     * 删除文件
     *
     * @param directory
     *            要删除文件所在目录
     * @param deleteFile
     *            要删除的文件
     * @param sftp
     * @return boolean
     */
    public static boolean deleteFile(String directory, String deleteFile,
                                     ChannelSftp sftp) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            // 删除文件
            sftp.rm(deleteFile);
        } catch (SftpException e) {
            logger.error("deleteFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }

    /**
     * 创建文件夹
     *
     * @param directory
     *            目标目录
     * @param creatDir
     *            要创建的文件
     * @param sftp
     * @return boolean
     */
    public static boolean createDir(String directory, String creatDir,
                                    ChannelSftp sftp) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            // 创建文件夹
            sftp.mkdir(creatDir);
        } catch (SftpException e) {
            logger.error("deleteFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }

    /**
     * 删除文件夹
     *
     * @param directory
     *            目标目录
     * @param deleteDir
     *            要删除的文件
     * @param sftp
     * @return boolean
     */
    public static boolean deleteDir(String directory, String deleteDir,
                                    ChannelSftp sftp) {
        try {
            // 进入指定目录
            sftp.cd(directory);
            // 删除文件夹
            sftp.rmdir(deleteDir);
        } catch (SftpException e) {
            logger.error("deleteFile -- SftpException:" + e.toString());
            return false;
        }
        return true;
    }

    /**
     * 列出目录下的文件
     *
     * @param directory
     *            要列出的目录
     * @param sftp
     * @return Vector<LsEntry>
     * @throws SftpException
     */
    @SuppressWarnings("unchecked")
    public static Vector<LsEntry> getListFiles(String directory,
                                               ChannelSftp sftp) {
        Vector<LsEntry> lsVec = null;
        try {
            // 列出指定目录下的所有文件和子目录
            lsVec = sftp.ls(directory);
        } catch (SftpException e) {
            logger.error("getListFiles -- SftpException:" + e.toString());
            return null;
        }
        return lsVec;
    }

    /**
     * 删除上传与下载临时目录的文件
     *
     * @param file
     *            要删除的文件
     */
    public static void deleteFileByTemp(File file) {
        // 目录是否存在
        if (file.exists()) {
            // 获取当前路径的文件列表
            File[] listFiles = file.listFiles();
            // 遍历文件列表
            for (File files : listFiles) {
                // 如果是文件夹,递归调用此方法
                if (files.isDirectory()) {
                    deleteFileByTemp(files);
                    // 如果是文件,直接删除
                } else if (files.isFile()) {
                    logger.info(files.getName() + "---" + files.delete());
                }
            }
            // 删除根目录文件
            logger.info(file.getName() + "---" + file.delete());
        } else {
            logger.info("当前路径不存在!");
        }
    }

    /**
     * 判断字符串是否为空
     *
     * @param str
     * @return boolean
     */
    public static boolean isEmpty(String str) {
        if (null == str || "".equals(str)) {
            return true;
        }
        return false;
    }

    /**
     * 判断对象是否为空
     *
     * @param
     * @return boolean
     */
    public static boolean isEmpty(Object obj) {
        if (null == obj || "".equals(obj)) {
            return true;
        }
        return false;
    }

    /**
     * 设置上传文件名
     *
     * @return String
     */
    public static String setFileName() {
        return new SimpleDateFormat("yyyyMMddHHmmss").format(new Date());
    }

    /**
     * 设置上传文件夹名
     *
     * @return String
     */
    public static String setDirName() {
        return new SimpleDateFormat("yyyyMMdd").format(new Date());
    }
}