package cc.smtweb.system.bpm.util.ftp;


import cc.smtweb.framework.core.util.DateUtil;
import cc.smtweb.framework.core.util.StringUtil;
import cc.smtweb.system.bpm.util.UtilLogger;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

//ftp管理类
public class FtpTaskManager {
    private static Map<String, FtpTaskManager> mapInstance = null;

    static {
        mapInstance = new HashMap<>();
    }

    //多线程
    private Map<Thread, IFtpUtil> mapThreadFtp = new HashMap<>();

    public static FtpTaskManager getInstance(String key, IFtpServerConfig ftpConfig) {
        key = key + "_" + (ftpConfig.isSFTP() ? 1: 0) + ftpConfig.getServerIp() + "_" + ftpConfig.getPort() + "_" + ftpConfig.getUserName();
        FtpTaskManager instance = mapInstance.get(key);
        if (instance == null) {
            synchronized (FtpTaskManager.class) {
                instance = mapInstance.get(key);
                if (instance == null) {
                    FtpTaskManager inst = new FtpTaskManager();
                    inst.init(ftpConfig);
                    instance = inst;
                    mapInstance.put(key, instance);
                }
            }
        }
        return instance;
    }

    private IFtpServerConfig ftpConfig = null;

    public FtpTaskManager() {
    }

    //初始化配置信息
    public void init(IFtpServerConfig ftpConfig) {
        this.ftpConfig = ftpConfig;
    }

    //获取一个ftp客户端
    public IFtpUtil getFtpUtil() {
        IFtpUtil ftp = mapThreadFtp.get(Thread.currentThread());
        if (ftp != null) return ftp;

        ftp = ftpConfig.isSFTP() ? new SFtpUtil(): new FtpUtil();
        boolean isConnect = ftp.login(ftpConfig);
        if (isConnect) {
            UtilLogger.info("FTP连接成功!");
        } else {
            UtilLogger.info("FTP连接失败!" + ftpConfig.getServerIp() + " " + ftpConfig.getPort() + " " + ftpConfig.getUserName() + " " + ftpConfig.getPassword());
        }
        return ftp;
    }

    //获取并加到线程中备用
    public IFtpUtil getThreadFtpUtil() {
        IFtpUtil ftp = getFtpUtil();
        ftp.setAutoFree(false);
        mapThreadFtp.put(Thread.currentThread(), ftp);
        return ftp;
    }

    //释放，和getThreadFtpUtil配对
    public void dispose() {
        IFtpUtil ftp = mapThreadFtp.remove(Thread.currentThread());
        if (ftp == null) return;
        ftp.setAutoFree(true);
        ftp.disconnect();
    }

    /**
     * 直接执行一个Ftp任务
     */
    public Object execute(FtpTask ftpTask) throws Exception {
        IFtpUtil ftp = getFtpUtil();
        if (!ftp.isConnected())
            throw new Exception("FTP连接失败（" + ftpConfig.getServerIp() + "/" + ftpConfig.getUserName() + "/" + (ftpConfig.isSFTP() ? "sftp": "ftp") + "）。");
        try {
            return ftpTask.execute(ftp);
        } finally {
            ftp.disconnect();
        }
    }

    //上传文件到Ftp服务器。传完后，根据设置删除本地文件
    public void uploadToFtp(final String remoteAttachName,
                            final String remoteFolderPath, final String localAttach,
                            final boolean isDelLocal) throws Exception {
        uploadToFtp(remoteAttachName, remoteFolderPath, new File(localAttach), isDelLocal);
    }

    public void uploadToFtp(final String remoteAttachName,
                            final String remoteFolderPath, final File localFile,
                            final boolean isDelLocal) throws Exception {
        this.execute(new FtpTask() {
            public Object execute(IFtpUtil ftp) throws Exception {
                if (ftp.uploadFile(remoteFolderPath, remoteAttachName, localFile)) {
                    if (isDelLocal) {//删除本地服务器的相应附件
                        localFile.delete();
                    }
                }
                return null;
            }
        });
    }

    private String getBakPath(String path) {
        path = StringUtil.isEmpty(path) ? DateUtil.getNowYm(): path;
        return "bak/" + path + "/";
    }

    //上传文件到Ftp服务器。传完后，根据设置删除本地文件
    public void downloadFile(final String remoteAttachName,
                             final String remoteFolderPath, final String localFile, final boolean isDelLocal) throws Exception {
        this.execute(new FtpTask() {
            public Object execute(IFtpUtil ftp) throws Exception {
                if (!ftp.existsFile(remoteFolderPath, remoteAttachName)) {
                    throw new Exception("服务器文件【" + remoteFolderPath + "/" + remoteAttachName + "】不存在！");
                }
                ftp.downloadFileEx(remoteFolderPath, remoteAttachName, localFile);
                if (isDelLocal) {
                    ftp.setRemoteDir("/");
                    final String bakPath = getBakPath(null);
                    ftp.mkdir(remoteFolderPath + "/" + bakPath);
                    ftp.rename(remoteFolderPath, remoteAttachName, bakPath + remoteAttachName);
                }
                return null;
            }
        });
    }

    public void delAndBakFile(String remoteFolderPath, String remoteAttachName) throws Exception {
        delAndBakFile(remoteFolderPath, remoteAttachName, null);

    }

    public void delAndBakFile(String remoteFolderPath, String remoteAttachName, String bakPath) throws Exception {
        this.execute(new FtpTask() {
            public Object execute(IFtpUtil ftp) throws Exception {
                if (!ftp.existsFile(remoteFolderPath, remoteAttachName)) return null;

                String path = getBakPath(bakPath);
                ftp.setRemoteDir("/");
                ftp.mkdir(remoteFolderPath + "/" + path);
                ftp.rename(remoteFolderPath, remoteAttachName, path + remoteAttachName);

                return null;
            }
        });
    }

    public void delFile(String delPath, String fileName) throws Exception {
        this.execute(new FtpTask() {
            public Object execute(IFtpUtil ftp) throws Exception {
                if (!ftp.existsFile(delPath, fileName)) return null;
                ftp.deleteFile(delPath, fileName);
                return null;
            }
        });
    }

    //从服务器下载文件到本地。传完后，根据设置删除远程目录文件
    public String[] listFileNames(final String remotePath) throws Exception {
        IFtpUtil ftp = getFtpUtil();
        if (!ftp.isConnected()) return new String[0];
        String[] fileNames;
        try {
            fileNames = ftp.listFileNames(remotePath);
        } finally {
            ftp.disconnect();
        }
        return fileNames;
    }

    public String[] downFolder(final String remotePath, final String localPath, final boolean isDelLocal, final IDownloadFileWorker worker, final String fileNamePrefix) throws Exception {
        final String[] files = listFileNames(remotePath);
        List<String> list = new ArrayList<>();
        this.execute(new FtpTask() {
            public Object execute(IFtpUtil ftp) throws Exception {
                for (String file : files) {
                    if (worker != null && !worker.isDownload(file, fileNamePrefix)) continue;
                    if (StringUtil.isNotEmpty(fileNamePrefix) && !file.startsWith(fileNamePrefix)) continue;
                    ftp.downloadFileEx(remotePath, file, localPath + "/" + file);
                    if (isDelLocal) {
                        ftp.setRemoteDir("/");
                        final String bakPath = getBakPath(null);
                        ftp.mkdir(remotePath + "/" + bakPath);
                        ftp.rename(remotePath, file, bakPath + file);
                    }
                    list.add(file);
                }
                return null;
            }
        });
        return list.toArray(new String[list.size()]);
    }

    public static void main(String[] args) throws Exception {
        FtpTaskManager ftp = FtpTaskManager.getInstance("test", new IFtpServerConfig() {
            @Override
            public boolean isSFTP() {
                return false;
            }

            @Override
            public String getServerIp() {
                return "127.0.0.1";
            }

            @Override
            public Integer getPort() {
                return 21;
            }

            @Override
            public String getUserName() {
                return "demo";
            }

            @Override
            public String getPassword() {
                return "1";
            }
        });
        ftp.uploadToFtp("S_2.jpg", "/", "f:\\temp\\tmp\\S_2.jpg", false);
//        ftp.uploadToFtp("民族5.png", "/", "f:\\temp\\temp\\民族5.png", false);
//        ftp.getThreadFtpUtil();
//        ftp.uploadToFtp("民族1.png", "/", "f:\\temp\\temp\\民族1.png", false);

//        ftp.uploadToFtp("民族2.png", "/", "f:\\temp\\temp\\民族2.png", false);
//        ftp.uploadToFtp("民族3.png", "/", "f:\\temp\\temp\\民族3.png", false);
//        ftp.downloadFile("民族2.png", "/", "f:/temp/民族2.png", true);
        /*String[] ss = ftp.downFolder("/", "f:/temp/test", true);
        for (String s: ss) {
            System.out.println(s);
        }*/

        ftp.downloadFile("S_1.jpg", "/", "f:/temp/S_21.jpg", true);
//        ftp.downloadFile("freesshd.log", "/", "f:/temp/freesshd.log", false);
        //ftp.downFolder("data/11", "f:/temp/11", true, "");

        ftp.dispose();
    }
}
