package com.bcxin.autodownloadupload.common.utils;


import org.apache.commons.net.ftp.*;

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

public class BcxinFtpClient {

    private FTPClient client;

    public BcxinFtpClient(){
        client = new FTPClient();
    }

    public FTPClient getClient() {
        return client;
    }

    public void setClient(FTPClient client) {
        this.client = client;
    }

    public BcxinFtpClient(boolean ftps) {
        if (ftps) {
            try {
                client = new FTPSClient(true);
            } catch ( Exception e) {
                e.printStackTrace();
            }
        } else {
            client = new FTPClient();
        }
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#changeDir(java.lang.String)
     */
    public boolean changeDir(String remotePath) throws Exception {
        return client.changeWorkingDirectory(remotePath);
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#connect(java.lang.String, java.lang.String, java.lang.String, int)
     */
    public boolean connect(String host, String username, String password, int port) throws Exception {
        boolean result = false;
        client.setConnectTimeout(30*1000);
        try{
            client.connect(host, port);    //连接FTP服务器
            client.login(username, password);//登录
            client.enterLocalPassiveMode();
            int reply = client.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)){
                client.disconnect();
                result = false;
            }
            result = true;
        }catch (IOException e){
            e.printStackTrace();
        }
        return result;
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#disconnect()
     */
    public void disconnect() throws Exception {
        if (client !=null) {
            client.logout();
            if(client.isConnected()) {
                client.disconnect();
            }
        }
    }


    protected boolean downloadFileAfterCheck(String remotePath, String localFile) throws IOException {
        boolean rst;
        FileOutputStream out = null;
        try {
            File file = new File(localFile);
            if (!file.exists()) {
                client.setFileType(FTP.BINARY_FILE_TYPE);
                out = new FileOutputStream(localFile);
                rst = client.retrieveFile(remotePath, out);
            } else {
                rst = true;
            }
        } finally {
            if (out != null) {
                out.close();
            }
        }
        if (out != null) {
            out.close();
        }
        return rst;
    }
    public boolean downloadFile(String remotePath, String localFile) throws IOException {

        boolean rst;
        FileOutputStream out = null;
        try {
            client.setFileType(FTP.BINARY_FILE_TYPE);
            out = new FileOutputStream(localFile);
            rst = client.retrieveFile(remotePath, out);
        } finally {
            if (out != null) {
                out.close();
            }
        }
        return rst;
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#listFileInDir(java.lang.String)
     */
    public List<String> listFileNameInDir(String remoteDir) throws Exception {
        if (changeDir(remoteDir)) {
            FTPFile[] files = client.listFiles();
            List<String> v = new ArrayList<String>();
            for (FTPFile file : files) {
                if (!file.isDirectory()) {
                    v.add(file.getName());
                }
            }
            return v;
        } else {
            return null;
        }
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#listFileInDir(java.lang.String)
     */
    public List<FTPFile> listFileInDir(String remoteDir) throws Exception {
        if (changeDir(remoteDir)) {
            FTPFile[] files = client.listFiles();
            List<FTPFile> v = new ArrayList<FTPFile>();
            for (FTPFile file : files) {
                if (!file.isDirectory()) {
                    v.add(file);
                }
            }
            return v;
        } else {
            return null;
        }
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#uploadFile(java.lang.String, java.lang.String)
     */
    public boolean uploadFile(String localFile, String remotePath) throws IOException {
        FileInputStream in = new FileInputStream(localFile);
        boolean rst;
        try {
            client.setFileType(FTP.BINARY_FILE_TYPE);
            rst = client.storeFile(remotePath, in);
        }catch (Exception e){
            rst = false;
            e.printStackTrace();
        }finally {
            in.close();
        }
        return rst;
    }
    public boolean uploadFile(InputStream in, String remotePath) throws IOException {
        boolean rst;
        try {
            client.setFileType(FTP.BINARY_FILE_TYPE);
            rst = client.storeFile(remotePath, in);
        } finally {
            in.close();
        }
        return rst;
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#listSubDirInDir(java.lang.String)
     */
    public List<String> listSubDirInDir(String remoteDir) throws Exception {
        if (changeDir(remoteDir)) {
            FTPFile[] files = client.listFiles();
            List<String> v = new ArrayList<String>();
            for (FTPFile file : files) {
                if (file.isDirectory()) {
                    v.add (file.getName());
                }
            }
            return v;
        } else {
            return null;
        }
    }
    public boolean createDirectory(String dirName) {
        return createMultiDirectory(dirName);
    }


    /**
     * 重命名远程FTP文件
     *
     * @param name
     *            新远程文件名称(路径-必须保证在同一路径下)
     *
     * @param remote
     *            远程文件路径
     *
     * @return  是否成功
     *
     */
    public String reName(String name,String remote){
        try {
            client.enterLocalPassiveMode();
            client.setFileType(FTP.BINARY_FILE_TYPE);
            String result = null;
            FTPFile[] files = client.listFiles(remote);
            if (files.length == 1) {
                boolean status = client.rename(remote, name);
                result = status ? "200" : "300";
            } else {
                result = "400";
            }
            return result;
        } catch (Exception e){
            e.printStackTrace();
        }
        return"";
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#isARemoteDirectory(java.lang.String)
     */
    public boolean isARemoteDirectory(String path) {
        String cache = "/";
        try {
            cache = client.printWorkingDirectory();
        } catch (NullPointerException e) {
            //nop
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            boolean isDir = changeDir(path);
            changeDir(cache);
            return isDir;
        } catch (IOException e) {
            //e.printStackTrace();
        } catch (Exception e) {
            //e.printStackTrace();
        }
        return false;
    }

    /* (non-Javadoc)
     * @see ftp.BcxinCommonFtp#getWorkingDirectory()
     */
    public String getWorkingDirectory() {
        try {
            return client.printWorkingDirectory();
        } catch (IOException e) {
        }
        return null;
    }


    //远程FTP服务器创建多级目录，创建目录失败或发生异常则返回false
    @SuppressWarnings("finally")
    private boolean createMultiDirectory(String multiDirectory) {
        boolean bool = false;
        try {
            String[] dirs = multiDirectory.split("/");
            //Window测试
            if(dirs.length==1) {
                dirs = multiDirectory.split(File.separator);
                client.changeWorkingDirectory(File.separator);
            }else {
                client.changeWorkingDirectory("/");
            }

            //按顺序检查目录是否存在，不存在则创建目录
            for(int i=1; dirs!=null&&i<dirs.length; i++) {
                if(!client.changeWorkingDirectory(dirs[i])) {
                    if(client.makeDirectory(dirs[i])) {
                        if(!client.changeWorkingDirectory(dirs[i])) {
                            return false;
                        }
                    }else {
                        return false;
                    }
                }
            }

            bool = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            return bool;
        }
    }





    /**
     * 删除服务器的文件
     *
     * @param deleteFiles 待删除的文件或者目录，为目录时，会逐个删除，
     *                    路径必须是绝对路径，如 "/1.png"、"/video/3.mp4"、"/images/2018"
     *                    "/" 表示用户根目录,则删除所有内容
     */
    public boolean deleteServerFiles(String deleteFiles) {
        boolean type = false;

        /**如果 FTP 连接已经关闭，或者连接无效，则直接返回*/
        if (!client.isConnected() || !client.isAvailable()) {
            System.out.println(">>>>>FTP服务器连接已经关闭或者连接无效*****放弃文件上传****");
            return false;
        }
        try {
            /** 尝试改变当前工作目录到 deleteFiles
             * 1）changeWorkingDirectory：变更FTPClient当前工作目录，变更成功返回true，否则失败返回false
             * 2）如果变更工作目录成功，则表示 deleteFiles 为服务器已经存在的目录
             * 3）否则变更失败，则认为 deleteFiles 是文件，是文件时则直接删除
             */
            boolean changeFlag = client.changeWorkingDirectory(deleteFiles);
            if (changeFlag) {
                /**当被删除的是目录时*/
                FTPFile[] ftpFiles = client.listFiles();
                for (FTPFile ftpFile : ftpFiles) {
                    System.out.println("----------------::::" + client.printWorkingDirectory());
                    if (ftpFile.isFile()) {
                        boolean deleteFlag = client.deleteFile(ftpFile.getName());
                        if (deleteFlag) {
                            System.out.println(">>>>>删除服务器文件成功****" + ftpFile.getName());
                            type = true;
                        } else {
                            System.out.println(">>>>>删除服务器文件失败****" + ftpFile.getName());
                            type = false;
                        }
                    } else {
                        /**printWorkingDirectory：获取 FTPClient 客户端当前工作目录
                         * 然后开始迭代删除子目录
                         */
                        String workingDirectory = client.printWorkingDirectory();
                        deleteServerFiles(workingDirectory + "/" + ftpFile.getName());
                    }
                }
                /**printWorkingDirectory：获取 FTPClient 客户端当前工作目录
                 * removeDirectory：删除FTP服务端的空目录，注意如果目录下存在子文件或者子目录，则删除失败
                 * 运行到这里表示目录下的内容已经删除完毕，此时再删除当前的为空的目录，同时将工作目录移动到上移层级
                 * */
                String workingDirectory = client.printWorkingDirectory();
                client.removeDirectory(workingDirectory);
                client.changeToParentDirectory();
            } else {
                /**deleteFile：删除FTP服务器上的文件
                 * 1）只用于删除文件而不是目录，删除成功时，返回 true
                 * 2）删除目录时无效,方法返回 false
                 * 3）待删除文件不存在时，删除失败，返回 false
                 * */
                boolean deleteFlag = client.deleteFile(deleteFiles);
                if (deleteFlag) {
                    System.out.println(">>>>>删除服务器文件成功****" + deleteFiles);
                    type = true;
                } else {
                    System.out.println(">>>>>删除服务器文件失败****" + deleteFiles);
                    type = false;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return type;
    }

    public String getEncodingName(String fileName) throws UnsupportedEncodingException {
        String cc = new String(fileName.getBytes(), "ISO-8859-1");
        return cc;
    }
}