package com.foreverwin.mesnac.common.ftp;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;

import java.io.*;
import java.net.SocketException;
import java.util.regex.Matcher;

@Component
@ConditionalOnProperty( prefix = "cappftp", name = { "server", "port", "username", "password", "uploadDir", "downloadDir" }, matchIfMissing = false )
public class CappFtpClient {

    private FTPClient ftp;

    @Value("${cappftp.server}")
    private String address;

    @Value("${cappftp.port}")
    private int port;

    @Value("${cappftp.username}")
    private String userName;

    @Value("${cappftp.password}")
    private String password;

    @Value("${cappftp.uploadDir}")
    private String uploadDir;

    @Value("${cappftp.downloadDir}")
    private String downloadDir;

    /**Ftp协议字符编码*/
    private String serverCharset = "ISO-8859-1";

    /**本体字符编码*/
    private String localCharset = "GBK";




    public FTPClient connect() throws Exception {
        try {
            //getFtpConf(ftpConfig);
            ftp = new FTPClient();
            ftp.setConnectTimeout(10000);
            ftp.connect(address, port);
            //2021/1/8 roc 修改读取文件阻塞时间
            //ftp.setSoTimeout(10 * 60 * 1000);
            ftp.setSoTimeout(30 * 1000);
            ftp.login(userName, password);
            //设置linux环境
            FTPClientConfig conf = new FTPClientConfig( FTPClientConfig.SYST_UNIX);
            ftp.configure(conf);

            //ftp.setControlEncoding(localCharset); // 中文支持
            //设置访问被动模式
            ftp.setRemoteVerificationEnabled(false);
            ftp.enterLocalPassiveMode();
            ftp.setFileType(ftp.BINARY_FILE_TYPE);// 设置传输模式
            return ftp;
        }
        catch (SocketException e) {
            throw new Exception("登录ftp服务器 " + address + " 失败,连接超时！", e);
        }
        catch (IOException e) {
            throw new Exception("登录ftp服务器 " + address + " 失败，FTP服务器无法打开！", e);
        }
        catch (Exception e) {
            throw new Exception("访问FTP服务器【" + address + "】失败！", e);
        }
    }

    /**
     * 上传文件
     *
     * @param file
     * @throws Exception
     */
    public void upload( File file ) throws Exception{
        connect();
        _upload( file );
        closeConnect();
    }

    /**
     * 上传文件
     *
     * @param remotePath
     * @param file
     * @throws IOException
     */
    public void upload( String remotePath, File file ) throws Exception{
        connect();
        _upload( remotePath, file );
        closeConnect();
    }

    /**
     * 下载文件
     *
     * @param remotePath
     * @param localPath
     * @throws Exception
     */
    public void download( String remotePath, String localPath ) throws Exception{
        connect();
        _download( remotePath, localPath );
        closeConnect();
    }

    public  InputStream downLoadFile(String filePath, String remoteFileName) throws Exception {
        InputStream in = null;
        // 下载文件
        try {
            connect();
            ftp.setControlEncoding("UTF-8"); // 中文支持
            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftp.enterLocalPassiveMode();
            remoteFileName = filePath + remoteFileName;
            String remote = new String(remoteFileName.getBytes(localCharset),serverCharset);

            in = ftp.retrieveFileStream(remote);

            if (null == in || ftp.getReplyCode() == 550) {
                throw new Exception("文件不存在");
            }

            return in;
        }
        catch (Exception e) {
            throw e;
        }
        finally {
            try {
                if (ftp != null || ftp.isConnected()) {
                    //ftpClient.logout();
                    ftp.disconnect();
                    ftp = null;
                }
            }
            catch (Exception e) {
                throw e;
            }
        }
    }
    /**
     * ftp下载文件到本地
     *
     * @param remoteFile
     * @param localFile
     * @throws Exception
     */
    public void download( String remoteFile, File localFile ) throws Exception{
        connect();
        _download( remoteFile, localFile );
        closeConnect();
    }

    /**
     * 删除文件
     *
     * @param remotePath
     * @throws IOException
     */
    public void deleteFile( String remotePath ) throws Exception{
        connect();
        _deleteFile( remotePath );
        closeConnect();
    }

    public void deleteFile1( String filePath ) throws Exception{
        connect();
        boolean b =ftp.deleteFile( filePath );
        closeConnect();
    }

    public void mkdirs( String remotePath ) throws Exception {
        connect();
        String[] paths = remotePath.split( Matcher.quoteReplacement(File.separator) );
        for( String p : paths ){
            ftp.makeDirectory( p );
            ftp.changeWorkingDirectory( p );
        }
        closeConnect();
    }

    private void _upload( File file ) throws Exception{
        if(file.isDirectory()){
            ftp.makeDirectory(file.getName());
            ftp.changeWorkingDirectory(file.getName());
            String[] files = file.list();
            for (int i = 0; i < files.length; i++) {
                File file1 = new File(file.getPath()+ File.separator +files[i] );
                _upload(file1);
            }
            ftp.changeToParentDirectory();
        }else{
            FileInputStream input = new FileInputStream(file);
            ftp.storeFile(file.getName(), input);
            input.close();
        }
    }


    private void _upload( String remotePath, File file ) throws Exception {
        String[] paths = remotePath.split( Matcher.quoteReplacement(File.separator) );
        for( String p : paths ){
            ftp.makeDirectory( p );
            ftp.changeWorkingDirectory( p );
        }
        _upload( file );
    }

    private void _download( String remotePath, String localPath ) throws Exception {
       FTPFile[] ftpFiles = ftp.listFiles( remotePath );
        if( ftpFiles.length > 0 ){
            for( FTPFile ftpFile : ftpFiles ){
                if( ftpFile.isDirectory() ){
                    _download( remotePath + File.separator + ftpFile.getName(), localPath + File.separator + ftpFile.getName() );
                }else{
                    File localDir = new File( localPath );
                    localDir.mkdirs();

                    File localFile = new File( localPath + File.separator + ftpFile.getName() );
                    localFile.createNewFile();
                    FileOutputStream fos = new FileOutputStream( localFile );
                    ftp.retrieveFile( remotePath + File.separator + ftpFile.getName(), fos );
                    fos.flush();
                    fos.close();
                }
            }
        }
    }


    private void _download( String remoteFile, File localFile ) throws Exception {

        localFile.createNewFile();
        FileOutputStream fos = new FileOutputStream( localFile );
        ftp.retrieveFile( remoteFile, fos );
        fos.flush();
        fos.close();
    }


    private void _deleteFile( String remotePath ) throws Exception {

        FTPFile[] ftpFiles = ftp.listFiles( remotePath );
        boolean b = false;
        if( ftpFiles.length > 0 ){
            for( FTPFile ftpFile : ftpFiles ){
                if( ftpFile.isDirectory() ){
                    _deleteFile( remotePath + File.separator + ftpFile.getName() );
                    b = ftp.removeDirectory( remotePath + File.separator + ftpFile.getName() );
                }else{
                    b= ftp.deleteFile( remotePath + File.separator + ftpFile.getName() );
                }
            }
        }
    }

    private String convertFtpCharset( String fileName ){
        try {
            return new String( fileName.getBytes( localCharset ), serverCharset );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return fileName;
    }

    private String convertLocalCharset( String fileName ){
        try {
            return new String( fileName.getBytes( serverCharset ), localCharset );
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return fileName;
    }

    private void closeConnect() {
        try{
            if( ftp != null && ftp.isConnected() ){
                ftp.logout();
                ftp.disconnect();
            }
        }catch (IOException e) {
            e.printStackTrace();
        }

    }

    public String getUploadDir(){
        return uploadDir;
    }

    public String getDownloadDir(){
        return downloadDir;
    }

    /**
     * 获取指定文件流
     * @param path
     * @return
     * @throws Exception
     */
    public InputStream getFtp(String path) throws Exception {
        login();
        ftp.enterLocalPassiveMode();
        InputStream in = ftp.retrieveFileStream(path);
        return in;
    }

    /**
     * 进入到服务器的某个目录下
     *
     * @param
     */
    public  boolean changeWorkingDirectory(String fDir) throws Exception {
        try {
            ftp.changeToParentDirectory();
            return ftp.changeWorkingDirectory(fDir);
        }
        catch (Exception ioe) {
            throw ioe;
        }
    }
    public FTPClient login() throws IOException{
        this.ftp=new FTPClient();
        this.ftp.connect(address,port);

        if(FTPReply.isPositiveCompletion(this.ftp.getReplyCode())){
            if(this.ftp.login(userName, password)){
                this.ftp.setControlEncoding("GBK");
                return this.ftp;
            }
        }

        if(this.ftp.isConnected()){
            this.ftp.disconnect();

        }

        return this.ftp;

    }
}
