package com.fjs.scenic.utils;

import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpSession;
import java.io.*;
import java.net.MalformedURLException;
import java.net.SocketException;

/**
 * FTP工具类
 */
public class FtpFileUtil {

    /**
     * 日志
     */
    private static Logger log = LoggerFactory.getLogger(FtpFileUtil.class);

    /**
     * ftp服务器ip地址
     */
    public static String FTP_ADDRESS;
    /**
     * 端口号
     */
    public static int FTP_PORT;
    /**
     * 用户名
     */
    public static String FTP_USERNAME;
    /**
     * 密码
     */
    public static String FTP_PASSWORD;
    /**
     * 图片路径
     */
    public static String FTP_BASEPATH;
    /**
     * 视频路径
     */
    public static String FTP_VOID_BASEPATH;
    /**
     * 图片访问的端口
     */
    public static String NGINX_PORT;

    /**
     * 初始化ftp服务器
     */
    public static FTPClient initFtpClient() {
        FTPClient ftpClient = new FTPClient();
        // 设置编码
        ftpClient.setControlEncoding("GBK");
        try {
            // 连接ftp服务器
            ftpClient.connect(FTP_ADDRESS, FTP_PORT);
            // 登录ftp服务器
            ftpClient.login(FTP_USERNAME, FTP_PASSWORD);
            // 是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.error("connect failed...ftp服务器:{}:{}", FTP_ADDRESS, FTP_PORT);
            }
            return ftpClient;
        } catch (MalformedURLException e) {
            log.error(e.toString());
        } catch (IOException e) {
            log.error(e.toString());
        }
        return null;
    }

    /**
     * 上传图片
     *
     * @param fileName 文件名
     * @param input
     * @return 图片的访问地址
     */
    public static String uploadFile(String fileName, InputStream input) {
        return uploadFile(fileName, input, FTPClient.BINARY_FILE_TYPE, FTP_BASEPATH);
    }


    /**
     * 上传视频
     *
     * @param fileName 文件名
     * @param input
     * @return 视频的访问地址
     */
    public static String uploadVoidFile(String fileName, InputStream input) {
        return uploadFile(fileName, input, FTPClient.BINARY_FILE_TYPE, FTP_VOID_BASEPATH);
    }

    /**
     * 上传文件
     *
     * @param fileName
     * @param input
     * @param fileType
     * @param pathName
     * @return
     */
    public static String uploadFile(String fileName, InputStream input, int fileType, String pathName) {
        FTPClient ftpClient = initFtpClient();
        try {
            ftpClient.connect(FTP_ADDRESS, FTP_PORT);
            // 登录ftp服务器
            ftpClient.login(FTP_USERNAME, FTP_PASSWORD);
            // 是否成功登录服务器
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                log.error("connect failed...ftp服务器:{}:{}", FTP_ADDRESS, FTP_PORT);
            }
            ftpClient.setFileType(fileType);
            ftpClient.makeDirectory(pathName);
            ftpClient.changeWorkingDirectory(pathName);
            ftpClient.enterLocalPassiveMode();
            ftpClient.storeFile(fileName, input);
            input.close();
            ftpClient.logout();
            return "http://" + FTP_ADDRESS + ":" + NGINX_PORT + pathName + "/" + fileName;
            //return "http://" + FTP_ADDRESS + ":" + NGINX_PORT + "/" + fileName;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                    log.error(ioe.toString());
                }
            }
        }
        return null;
    }

    /** */
    /**
     * 上传文件到服务器,新上传和断点续传
     *
     * @param remoteFile 远程文件名，在上传之前已经将服务器工作目录做了改变
     * @param localFile  本地文件File句柄，绝对路径
     * @return
     * @throws IOException
     */
    public static String uploadFile(String remoteFile, File localFile,HttpSession session,String sessionID, long remoteSize) throws IOException {
        FTPClient ftpClient = initFtpClient();
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        ftpClient.makeDirectory(FTP_VOID_BASEPATH);
        ftpClient.changeWorkingDirectory(FTP_VOID_BASEPATH);
        ftpClient.enterLocalPassiveMode();
        //显示进度的上传
        long step = localFile.length() / 100;
        long process = 0;
        long localreadbytes = 0L;
        RandomAccessFile raf = new RandomAccessFile(localFile, "r");
        OutputStream out = ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"), "iso-8859-1"));
        //断点续传
        if (remoteSize > 0) {
            ftpClient.setRestartOffset(remoteSize);
            process = remoteSize / step;
            raf.seek(remoteSize);
            localreadbytes = remoteSize;
        }
        byte[] bytes = new byte[1024];
        int c;
        while ((c = raf.read(bytes)) != -1) {
            out.write(bytes, 0, c);
            localreadbytes += c;
            if (localreadbytes / step != process) {
                process = localreadbytes / step;
                System.out.println("上传进度:" + process);
                //TODO 汇报上传状态
                session.setAttribute(sessionID,process+"");
            }
        }
        out.flush();
        raf.close();
        out.close();
        ftpClient.logout();
        return "http://" + FTP_ADDRESS + ":" + NGINX_PORT + FTP_VOID_BASEPATH + "/" + localFile.getName();

    }


    /**
     * 上传带进度
     * @param file 上传文件
     * @return
     * @throws IOException
     */
    public static String uploadFile(MultipartFile file,HttpSession sessoin,String sessionID) throws IOException {
        // 获取文件名
        String fileName = file.getOriginalFilename();
        // 获取文件后缀
        String prefix = fileName.substring(fileName.lastIndexOf("."));
        // 用uuid作为文件名，防止生成的临时文件重复
        final File excelFile = File.createTempFile(ImgeNameUtils.genImageName(), prefix);
        // MultipartFile to File
        file.transferTo(excelFile);
        String url = uploadFile(excelFile.getName(), excelFile,sessoin,sessionID, 0);
        //程序结束时，删除临时文件
        deleteFile(excelFile);
        return url;
    }

    /**
     * 删除
     *
     * @param files
     */
    private static void deleteFile(File... files) {
        for (File file : files) {
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 删除文件
     *
     * @param fileName 文件名
     * @return
     */
    public static boolean deleteFile(String fileName) {
        boolean flag = false;
        FTPClient ftpClient = initFtpClient();
        try {
            //切换FTP目录
            ftpClient.changeWorkingDirectory(FTP_BASEPATH);
            ftpClient.dele(fileName);
            ftpClient.logout();
            flag = true;
            log.info("删除文件成功.");
        } catch (Exception e) {
            log.error("删除文件失败:{}", e.toString());
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return flag;
    }

    /**
     * 从FTP服务器下载文件(图片)
     *
     * @param localPath 下载到本地的位置 格式：H:/download
     * @param fileName  文件名称
     */
    public static void downloadFtpFile(String localPath, String fileName) {
        downloadFtpFile(localPath, fileName, FTPClient.BINARY_FILE_TYPE, FTP_BASEPATH);
    }

    /**
     * 下载文件
     *
     * @param localPath
     * @param fileName
     * @param filetype
     * @param pathName
     */
    public static void downloadFtpFile(String localPath, String fileName, int filetype, String pathName) {

        FTPClient ftpClient = initFtpClient();

        try {
            ftpClient.setFileType(filetype);
//            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(pathName);

            File localFile = new File(localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(fileName, os);
            os.close();
            ftpClient.logout();

        } catch (FileNotFoundException e) {
            log.error(e.toString());
            System.out.println("没有找到" + pathName + "文件");
            e.printStackTrace();
        } catch (SocketException e) {
            log.error(e.toString());
            System.out.println("连接FTP失败.");
            e.printStackTrace();
        } catch (IOException e) {
            log.error(e.toString());
            e.printStackTrace();
            System.out.println("文件读取错误。");
            e.printStackTrace();
        }
    }

    /**
     * 下载视频
     *
     * @param localPath
     * @param fileName
     */
    public static void downloadFtpVoidFile(String localPath, String fileName) {
        downloadFtpFile(localPath, fileName, FTPClient.BINARY_FILE_TYPE, FTP_VOID_BASEPATH);
    }
}