package com.dxhy.oss.service;

import com.dxhy.oss.utils.SftpPool;
import com.dxhy.oss.utils.SftpPoolException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.springframework.stereotype.Service;

import java.io.*;
import java.util.ArrayList;
import java.util.List;

@Slf4j
public class FtpService {

    private final SftpPool pool;

    public FtpService(SftpPool pool) {
        this.pool = pool;
    }

    /**
     * ftp上传文件
     *
     * @param serviceDec
     * @param fileName
     * @param localDec 本地目录
     * @return
     */
    public boolean uploadFile( String serviceDec, String fileName, String localDec) throws InterruptedException {
        FTPClient ftpClient = null;
        InputStream inputStream = null;
        boolean result =true;
        try {
            inputStream = new FileInputStream(new File(localDec));
            log.info("开始上传文件");
            ftpClient = pool.borrowObject();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            createDirecroty(ftpClient, serviceDec);
            ftpClient.makeDirectory(serviceDec);
            ftpClient.changeWorkingDirectory(serviceDec);
            ftpClient.storeFile(fileName, inputStream);
            inputStream.close();
            ftpClient.logout();
            log.info("上传文件成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("上传文件失败" + e);
            result =false;
        } finally {
            try {
                log.info("回收线程");
                pool.returnObject(ftpClient);
                if (null != inputStream) {
                    inputStream.close();
                }
            } catch (IOException e) {
                log.error("上传文件失败" + e);
                result =false;
            }
        }
        return result;
    }

    public boolean deleteFile(String directory, String deleteFile) {
        FTPClient ftpClient = null;
        try {
            ftpClient = pool.borrowObject();
            return ftpClient.deleteFile(directory + File.separator + deleteFile);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            if (ftpClient != null) {
                log.info("回收线程");
                pool.returnObject(ftpClient);
            }
        }
    }

    private static boolean createDirecroty(FTPClient ftpClient, String remote) throws IOException {
        boolean success = true;
        String directory = remote + "/";
        // 如果远程目录不存在，则递归创建远程服务器目录
        if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(ftpClient, new String(directory))) {
            int start = 0;
            int end = 0;
            if (directory.startsWith("/")) {
                start = 1;
            } else {
                start = 0;
            }
            end = directory.indexOf("/", start);
            String path = "";
            String paths = "";
            while (true) {
                String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1");
                path = path + "/" + subDirectory;
                if (!existFile(ftpClient, path)) {
                    if (makeDirectory(ftpClient, subDirectory)) {
                        changeWorkingDirectory(ftpClient, subDirectory);
                    } else {
                        log.info("创建目录[" + subDirectory + "]失败");
                        changeWorkingDirectory(ftpClient, subDirectory);
                    }
                } else {
                    changeWorkingDirectory(ftpClient, subDirectory);
                }

                paths = paths + "/" + subDirectory;
                start = end + 1;
                end = directory.indexOf("/", start);
                // 检查所有目录是否创建完毕
                if (end <= start) {
                    break;
                }
            }
        }
        return success;
    }

    //改变目录路径
    private static boolean changeWorkingDirectory(FTPClient ftpClient, String directory) {
        boolean flag = true;
        try {
            flag = ftpClient.changeWorkingDirectory(directory);
            if (flag) {
                log.info("进入文件夹" + directory + " 成功！");

            } else {
                log.info("进入文件夹" + directory + " 失败！开始创建文件夹");
            }
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return flag;
    }

    //判断ftp服务器文件是否存在
    private static boolean existFile(FTPClient ftpClient, String path) throws IOException {
        boolean flag = false;
        FTPFile[] ftpFileArr = ftpClient.listFiles(path);
        if (ftpFileArr.length > 0) {
            flag = true;
        }
        return flag;
    }

    //创建目录
    private static boolean makeDirectory(FTPClient ftpClient, String dir) {
        boolean flag = true;
        try {
            flag = ftpClient.makeDirectory(dir);
            if (flag) {
                log.info("创建文件夹" + dir + " 成功！");

            } else {
                log.info("创建文件夹" + dir + " 失败！");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 获取FTP某一特定目录下的所有文件名称
     *
     * @param ftpClient  已经登陆成功的FTPClient
     * @param ftpDirPath FTP上的目标文件路径
     */
    public static List getFileNameList(FTPClient ftpClient, String ftpDirPath) {
        List list = new ArrayList();
        try {
            if (ftpDirPath.startsWith("/") && ftpDirPath.endsWith("/")) {
                // 通过提供的文件路径获取FTPFile对象列表
                FTPFile[] files = ftpClient.listFiles(ftpDirPath);
                // 遍历文件列表，打印出文件名称
                for (int i = 0; i < files.length; i++) {
                    FTPFile ftpFile = files[i];
                    // 此处只打印文件，未遍历子目录（如果需要遍历，加上递归逻辑即可）
                    if (ftpFile.isFile()) {
//                        log.info(ftpDirPath + ftpFile.getName());
                        list.add(ftpFile.getName());
                    }
                }
                log.info("当前FTP路径可用");
            } else {
                log.info("当前FTP路径不可用");
            }
        } catch (IOException e) {
            log.error("错误" + e);
        }
        return list;
    }
    /**
     * @param servicePath ftp的路径
     * @param fileName 文件名称
     * @param localFilePath 下载到本地的文件夹
     * @return
     */
    public boolean downloadFile(String servicePath, String fileName, String localFilePath) {
        FTPClient ftpClient;
        try {
            ftpClient = pool.borrowObject();
            String name = dowFile(ftpClient, servicePath, fileName, localFilePath);
            if (name != null && !name.equals("")){
                return true;
            }
        } catch (SftpPoolException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     *
     * @param ftpClient
     * @param servicePath ftp的路径
     * @param fileName 文件名称
     * @param localFilePath 下载到本地的文件夹
     * @return
     */
    private static String dowFile(FTPClient ftpClient, String servicePath, String fileName, String localFilePath) {
        InputStream is = null;
        FileOutputStream fos = null;
        try {
            ftpClient.enterLocalPassiveMode();
            is = ftpClient.retrieveFileStream(servicePath + fileName);// 获取ftp上的文件
            directoryIsExists(localFilePath);
            fos = new FileOutputStream(new File(localFilePath + fileName));
            // 文件读取方式一
            int i;
            byte[] bytes = new byte[1024];
            while ((i = is.read(bytes)) != -1) {
                fos.write(bytes, 0, i);
            }
            ftpClient.completePendingCommand();
            log.info("FTP文件下载成功！");
        } catch (Exception e) {
            log.error("FTP文件下载失败！" + e);
        } finally {
            try {
                if (fos != null) {fos.close();}
                if (is != null) {is.close();}
            } catch (IOException e) {
                log.error("下载流关闭失败" + e);
                return null;
            }
        }
        return localFilePath + fileName;
    }


    public static void directoryIsExists(String path) {
        File directory = new File(path);
        if (directory.exists()) {
            return;
        }

        if (!directory.mkdir()) {
            return;
        }

        if (directory.canWrite()) {
            return;
        }

        boolean setWritable = directory.setWritable(true);
        log.info("是否创建文件  directoryIsExists ：{} ", setWritable);

    }
}
