package com.rrtx.services.common.utils;

import com.rrtx.services.common.exception.BusinessCodeException;
import com.rrtx.fap.starter.genid.service.IdService;
import com.rrtx.fap.starter.translate.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.multipart.MultipartFile;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.*;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 图片上传到图片服务器
 *
 * @author ZHANGZZ@MINPAY.CC
 */
@Slf4j
public class FtpClientUtil {

    @Autowired
    private IdService idService;

    /**
     * 获得连接FTP方式
     *
     * @param hostName FTP服务器地址
     * @param port     FTP服务器端口
     * @param userName FTP登录用户名
     * @param passWord FTP登录密码
     * @return
     */
    public FTPClient getConnectionFTP(String hostName, int port, String userName, String passWord) {
        //创建FTPClient对象
        FTPClient ftp = new FTPClient();
        try {
            //连接FTP服务器
            ftp.connect(hostName, port);
            //下面三行代码必须要，而且不能改变编码格式，否则不能正确下载中文文件
            ftp.setControlEncoding("GBK");
            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
            conf.setServerLanguageCode("zh");
            ftp.enterLocalPassiveMode();
            //登录ftp
            ftp.login(userName, passWord);
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                ftp.disconnect();
                System.out.println("连接服务器失败");
            } else {
                System.out.println("登陆服务器成功");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return ftp;
    }

    /**
     * 关闭连接FTP方式
     *
     * @param ftp FTPClient对象
     * @return
     */
    public boolean closeFTP(FTPClient ftp) {
        if (ftp.isConnected()) {
            try {
                ftp.disconnect();
                System.out.println("ftp已经关闭");
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return false;
    }

    /**
     * 上传文件FTP方式
     *
     * @param ftp         FTPClient对象
     * @param rootPath    FTP服务器目录
     * @param subDir      FTP服务器子目录
     * @param fileName    本地文件路径
     * @param inputStream 输入流
     * @return
     */
    public boolean uploadFile(FTPClient ftp, String rootPath, String subDir, String fileName, InputStream inputStream) {
        boolean success = false;
        try {
            ftp.changeWorkingDirectory(rootPath);//转移到指定FTP服务器目录
            FTPFile[] fs = ftp.listFiles();//得到目录的相应文件列表
            fileName = FtpClientUtil.changeName(fileName, fs);
            fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
            rootPath = new String(rootPath.getBytes("GBK"), "ISO-8859-1");
            createDirectory(ftp, rootPath, subDir);
//                 //转到指定上传目录
            ftp.changeWorkingDirectory(rootPath + subDir);
            //将上传文件存储到指定目录
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            //如果缺省该句 传输txt正常 但图片和其他格式的文件传输出现乱码
            boolean isFtp = ftp.storeFile(fileName, inputStream);
            log.info("是否真实上传成功：" + isFtp);
            //关闭输入流
            inputStream.close();
            //退出ftp
            ftp.logout();
            //表示上传成功
            success = true;
            System.out.println("上传成功。。。。。。");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 创建远程目录
     *
     * @param ftp      FTPClient对象
     * @param rootPath FTP服务器目录
     * @param subDir   FTP服务器子目录
     * @return
     * @throws IOException
     */
    public boolean createDirectory(FTPClient ftp, String rootPath, String subDir)
            throws IOException {
        changeWorkingDirectory(ftp, rootPath);
        // 如果远程目录不存在，则递归创建远程服务器目录
        int start = 0;
        int index = subDir.indexOf("/", start);
        // 日志记录，增加了什么目录
        String addedPath = "";
        while (true) {
            String dir = subDir.substring(start, index);
            if (!ftp.changeWorkingDirectory(new String(dir.getBytes("GBK"),
                    "iso-8859-1"))) {
                if (makeDirectory(ftp, dir)) {
                    addedPath += "/" + dir;
                    changeWorkingDirectory(ftp, dir);
                } else {
                    return false;
                }
            }
            start = index + 1;
            index = subDir.indexOf("/", start);
            // 检查所有目录是否创建完毕
            if (start >= index) {
                break;
            }
        }
        return true;
    }

    /**
     * 创建目录
     * @param ftp
     * @param pathname
     * @return
     * @throws IOException
     */
    public boolean makeDirectory(FTPClient ftp, String pathname)
            throws IOException {
        return FTPReply.isPositiveCompletion(ftp.mkd(pathname));
    }

    /**
     * 变更服务器当前目录
     * @param ftp
     * @param pathname
     * @return
     * @throws IOException
     */
    public boolean changeWorkingDirectory(FTPClient ftp, String pathname)
            throws IOException {
        return FTPReply.isPositiveCompletion(ftp.cwd(pathname));
    }

    /**
     * 删除文件FTP方式
     *
     * @param ftp      FTPClient对象
     * @param path     FTP服务器上传地址
     * @param fileName FTP服务器上要删除的文件名
     * @return
     */
    public boolean deleteFile(FTPClient ftp, String path, String fileName) {
        boolean success = false;
        try {
            ftp.changeWorkingDirectory(path);//转移到指定FTP服务器目录
            fileName = new String(fileName.getBytes("GBK"), "ISO-8859-1");
            path = new String(path.getBytes("GBK"), "ISO-8859-1");
            ftp.deleteFile(fileName);
            ftp.logout();
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 上传文件FTP方式
     *
     * @param ftp       FTPClient对象
     * @param path      FTP服务器上传地址
     * @param fileName  本地文件路径
     * @param localPath 本里存储路径
     * @return boolean
     */
    public boolean downFile(FTPClient ftp, String path, String fileName, String localPath) {
        boolean success = false;
        try {
            ftp.changeWorkingDirectory(path);//转移到FTP服务器目录
            FTPFile[] fs = ftp.listFiles(); //得到目录的相应文件列表
            for (FTPFile ff : fs) {
                if (ff.getName().equals(fileName)) {
                    File localFile = new File(localPath + "\\" + ff.getName());
                    OutputStream outputStream = new FileOutputStream(localFile);
                    //将文件保存到输出流outputStream中
                    ftp.retrieveFile(new String(ff.getName().getBytes("GBK"), "ISO-8859-1"), outputStream);
                    outputStream.flush();
                    outputStream.close();
                    System.out.println("下载成功");
                }
            }
            ftp.logout();
            success = true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return success;
    }

    /**
     * 判断是否有重名文件
     *
     * @param fileName
     * @param fs
     * @return
     */
    public static boolean isFileExist(String fileName, FTPFile[] fs) {
        for (int i = 0; i < fs.length; i++) {
            FTPFile ff = fs[i];
            if (ff.getName().equals(fileName)) {
                return true; //如果存在返回 正确信号
            }
        }
        return false; //如果不存在返回错误信号
    }

    /**
     * 根据重名判断的结果 生成新的文件的名称
     *
     * @param fileName
     * @param fs
     * @return
     */
    public static String changeName(String fileName, FTPFile[] fs) {
        int n = 0;
        //      fileName = fileName.append(fileName);
        while (isFileExist(fileName.toString(), fs)) {
            n++;
            String a = "[" + n + "]";
            int b = fileName.lastIndexOf(".");//最后一出现小数点的位置
            int c = fileName.lastIndexOf("[");//最后一次"["出现的位置
            if (c < 0) {
                c = b;
            }
            StringBuffer name = new StringBuffer(fileName.substring(0, c));//文件的名字
            StringBuffer suffix = new StringBuffer(fileName.substring(b + 1));//后缀的名称
            fileName = name.append(a) + "." + suffix;
        }
        return fileName.toString();
    }

    /**
     * 文件上传数据准备
     * @param myfiles
     * @param fileType 文件类型 00图片 01文件 02视频
     * @param prefixesFlag 文件名前缀
     * @return Map
     * @throws BusinessCodeException
     */
    public Map<String, Object> uploadFileDataDeal(MultipartFile myfiles, String fileType, String prefixesFlag, String subFileName) throws BusinessCodeException{
        String ftp_ip = ConvertUtil.translate("FTP_SERVER", "FTP_IP");
        String ftp_port = ConvertUtil.translate("FTP_SERVER", "FTP_PORT");
        String ftp_username = ConvertUtil.translate("FTP_SERVER", "FTP_USERNAME");
        String ftp_password = ConvertUtil.translate("FTP_SERVER", "FTP_PASSWORD");
        String ftp_path = ConvertUtil.translate("FTP_SERVER", "FILE_PATH_"+fileType);
        String ftp_base_path= ConvertUtil.translate("FTP_SERVER", "FILE_SERVER_BASE_PATH");
        String ftp_url = ConvertUtil.translate("FTP_SERVER", "FILE_SERVER_URL");

        InputStream in = null;
        String saveFileName = "";
        String subDir = "";
        try {
            String fileName = myfiles.getOriginalFilename();
            // 文件名后缀
            String fileNameSuffix = fileName.split("\\.")[fileName.split("\\.").length - 1];
            // 文件重命名
            saveFileName = prefixesFlag + subFileName + "."+ fileNameSuffix;
            log.info(saveFileName);
            in = myfiles.getInputStream();
            int ftpP = 21;
            if(!StringUtils.isEmpty(ftp_port)){
                ftpP = Integer.valueOf(ftp_port);
            }
            // 获取当前时间
            String nowDate = DateUtil.getDateFormat(new Date(), "yyyyMMdd");
            subDir = ftp_path+ nowDate +"/";
            FTPClient ftp = getConnectionFTP(ftp_ip, ftpP, ftp_username,ftp_password);
            ftp.enterLocalActiveMode();
            uploadFile(ftp, ftp_base_path, subDir, saveFileName, in);
            closeFTP(ftp);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e2) {
                e2.printStackTrace();
            }
        }
        String url = ftp_url.concat(subDir).concat(saveFileName);
        log.info("文件访问路径：" + url);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("url", url);
        return map;
    }

    /**
     * @param args
     * @throws FileNotFoundException 测试程序
     */
    public static void main(String[] args) throws FileNotFoundException {

        String path = "服务器地址";
        File f1 = new File("D:\\a.txt");
        String filename = f1.getName();
        System.out.println(filename);
        FtpClientUtil a = new FtpClientUtil();
        InputStream input = new FileInputStream(f1);
        FTPClient ftp = a.getConnectionFTP("ip", 21, "username", "password");
//             a.uploadFile(ftp, path, filename, input);
        a.closeFTP(ftp);
    }

}
