package im.zksy.yjmqserver.common.util;

import im.zksy.yjmqserver.system.model.Ftp;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;

import javax.annotation.PostConstruct;
import java.io.*;
import java.net.MalformedURLException;
import java.net.SocketException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class FTPUtils {
    private static Logger log = LoggerFactory.getLogger(FTPUtils.class);
    @Value("${ftp.host}")
    private String ftpHost ;
    private List<Ftp> ftps = new ArrayList<Ftp>();

    @Autowired
    private Ftp ftpUrl;
    @Autowired
    private static FTPUtils ftp;

    @PostConstruct
    private void initHostMap(){
        ftp=this;

        if(ftpHost==null ){
            log.error("ftp存储组未配置，请先配置");
            return;
        }else{
            if(ftpHost.split(":").length==4) {
                ftpUrl.setFtpIp(ftpHost.split(":")[0]);
                ftpUrl.setFtpPort(Integer.parseInt(ftpHost.split(":")[1]));
                ftpUrl.setFtpUsername(ftpHost.split(":")[2]);
                ftpUrl.setFtpPassword(ftpHost.split(":")[3]);
            }else{
                log.error("ftp配置错误");
            }
            ftp.ftpUrl=this.ftpUrl;
        }
    }
    public static void downLoadFile(String path, OutputStream toClient) {
        BufferedInputStream bis = null;
        InputStream is = null;
        try {
            if (path.toUpperCase().indexOf("FTP") != -1) {
                String tempUrl = path;
                tempUrl = tempUrl.replaceAll("\\\\", "/");
                URL url = new URL(tempUrl);
                is = url.openStream();
                bis = new BufferedInputStream(is);
                IOUtils.copy(bis, toClient);
                return;
            }
        } catch (Exception e) {
            log.error("FTP下载图片出错", e);
        } finally {
            IOUtils.closeQuietly(toClient);
            IOUtils.closeQuietly(is);
            IOUtils.closeQuietly(bis);
        }
    }

    public static byte[] getFtpPicBytes(String path) {
        URL url = null;
        try {
            url = new URL(path);
        } catch (MalformedURLException e) {
            log.error("FTP URL路径错误"+e.toString());
        }
        byte[] buffer = null;
        try (InputStream is = url.openStream();ByteArrayOutputStream bos = new ByteArrayOutputStream(1000)){
            byte[] b = new byte[1000];
            int n;
            while ((n = is.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            buffer = bos.toByteArray();

        }catch (Exception e) {
            log.error("FTP下载图片出错", e);
        }
        return buffer;
    }


    //ftp图片上传，图片参数为base64封装的String
    public  boolean uploadFile( String path, String filename, String inputImg)  {
        boolean flag = true;
        FTPClient ftpClient = null;
        ByteArrayInputStream input = null;
        try {
            if (inputImg == null) {
                return false;
            }
            //base64解码
            BASE64Decoder decoder = new BASE64Decoder();
            byte[] b_img = decoder.decodeBuffer(inputImg);
            input = new ByteArrayInputStream(b_img);
            ftpClient = connectServer();
            //new ByteArrayInputStream
            if (ftpClient.isConnected()) {
                changeWorkingDirectory(ftpClient, path);
                flag = ftpClient.storeFile(filename, input);
                if (flag) {
                    log.info("FTP上传文件成功！");
                } else {
                    flag = false;
                    log.info("FTP上传文件失败！");
                }
            }
        } catch (Exception e) {
            flag = false;
            log.error("FTP文件上传失败！", e.toString());
        } finally {
            IOUtils.closeQuietly(input);
            closeConnect(ftpClient);
        }
        return flag;
    }

    public  boolean uploadFile(Ftp ftpUrl, String path, String filename, InputStream input){
        boolean flag = true;
        FTPClient ftpClient = null;
        try {
            ftpClient = connectServer();
            if (ftpClient.isConnected()) {
                changeWorkingDirectory(ftpClient, path);
                flag = ftpClient.storeFile(filename, input);
                if (flag) {
//                    log.info("FTP upload success！");
                } else {
                    log.info("FTP upload fail！");
                }
            } else {
                flag = false;
//                log.info("FTP server refused connection ！");
            }
        } catch (IOException e) {
            flag = false;
            log.error("FTP upload fail！", e);
        } catch (Exception e) {
            flag = false;
            log.error("FTP upload fail！", e);
        } finally {
            IOUtils.closeQuietly(input);
            closeConnect(ftpClient);
        }
        return flag;
    }

    /*
     * 得到配置文件中的FTP服务器地址
     */
    public static String getFtpUrl(Ftp ftpUrl) {
        StringBuffer buffer = new StringBuffer();
        buffer.append("ftp://");
        String ftpUsername = ftpUrl.getFtpUsername();
        if (ftpUsername != null && ftpUsername.trim().length() > 0) {
            buffer.append(ftpUsername);
            buffer.append(":");
            buffer.append(ftpUrl.getFtpPassword());
            buffer.append("@");
        }
        buffer.append(ftpUrl.getFtpIp());
        if (ftpUrl.getFtpPort() != null) {
            buffer.append(":");
            buffer.append(ftpUrl.getFtpPort());
        }
        buffer.append("/");
        return buffer.toString();
    }

    public  boolean deleteFileFromFtpUrl(String ftpUrl) throws Exception {
        boolean flag = false;
        if (null == ftpUrl || StringUtils.isBlank(ftpUrl)) {
            throw new Exception("ftpUrl串为空");
        }
        Map<String, String> result = getFtpInfoMapByFullPath(ftpUrl);
        String ftpUser = result.get("ftpUser");
        String ftpPassword = result.get("ftpPassword");
        String ftpIp = result.get("ftpIp");
        String ftpPort = result.get("ftpPort");
        String fileName = result.get("fileName");
        String path = result.get("path");
        Ftp ftp = FTPUtils.getFtpUrlObj(ftpIp, ftpPort, ftpUser, ftpPassword);
        FTPClient ftpClient = connectServer();
        if (null == ftpClient) {
            throw new Exception("ftp登录失败 ");
        } else {
            String fullPath = (null == path || "".equals(path.trim())) ? fileName : (path + "/" + fileName);
            try {
                flag = ftpClient.deleteFile(fullPath);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return flag;

    }

    /**
     * @param ftpUrlStr
     * @return
     * @throws Exception
     * @author sunw 通过图片路径
     * 获得ftpuser,ftppassword,ftpip,ftpport,在fpt上的文件路径,文件realname
     */
    private static Map<String, String> getFtpInfoMapByFullPath(String ftpUrlStr) throws Exception {
        if (null == ftpUrlStr || "".equals(ftpUrlStr.trim())) {
            throw new Exception("ftpstr串为空");
        }
        ftpUrlStr = ftpUrlStr.replaceAll("\\\\", "/");
        ftpUrlStr = changeUrlCharater(ftpUrlStr);
        String array[] = ftpUrlStr.split("/");
        String[] ftpUserPasswordAndIpPort = array[2].split("@");
        String[] ftpUserAndPassword = ftpUserPasswordAndIpPort[0].split(":");
        String[] ftpIpAndPort = ftpUserPasswordAndIpPort[1].split(":");
        String ftpUser = ftpUserAndPassword[0];
        String ftpPassword = ftpUserAndPassword[1];
        String ftpIp = ftpIpAndPort[0];
        String ftpPort = ftpIpAndPort.length > 1 ? ftpIpAndPort[1] : "";
        String fileName = array[array.length - 1];// 获得文件名
        Map<String, String> resultMap = new HashMap<String, String>();
        resultMap.put("ftpUser", ftpUser);
        resultMap.put("ftpPassword", ftpPassword);
        resultMap.put("ftpIp", ftpIp);
        resultMap.put("ftpPort", ftpPort);
        resultMap.put("fileName", fileName);
        String path = "";
        for (int i = 3; i < array.length - 1; i++) {
            if (i != array.length - 2) {
                path += array[i] + "/";
            } else {
                path += array[i];
            }
        }
        resultMap.put("path", path);
        return resultMap;
    }



    public static String changeUrlCharater(String tempUrl) {
        tempUrl = tempUrl.replaceAll("%", "%25").replaceAll("#", "%23").replaceAll("\\+", "%2B").replaceAll("&", "%26");
        tempUrl = tempUrl.replaceAll("=", "%3D").replaceAll("\\?", "%3F");
        return tempUrl;
    }

    /**
     * 连接到服务器
     */
    private  FTPClient connectServer() {
        FTPClient ftpClient = null;
        try {
            ftpClient = new FTPClient();
            ftpClient.setControlEncoding("utf-8");
            if (ftp.ftpUrl.getFtpPort() != null) {
                ftpClient.setDefaultPort(ftp.ftpUrl.getFtpPort());
            }
            ftpClient.connect(ftp.ftpUrl.getFtpIp());
            ftpClient.login(ftp.ftpUrl.getFtpUsername(), ftp.ftpUrl.getFtpPassword());
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
//			ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
            ftpClient.setBufferSize(10240);
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                System.err.println("FTP server refused connection.");
                log.info("FTP 服务拒绝连接！");
            }
        } catch (SocketException e) {
            log.error("登录ftp服务器 " + ftp.ftpUrl.getFtpIp() + " 失败,连接超时！", e);
        } catch (IOException e) {
            log.error("登录ftp服务器 " + ftp.ftpUrl.getFtpIp() + " 失败，FTP服务器无法打开！", e);
        }
        return ftpClient;
    }

    /**
     * 关闭连接
     */
    private static void closeConnect(FTPClient ftpClient) {
        try {
            if (ftpClient != null) {
                if (ftpClient.isConnected() == true) {
                    ftpClient.logout();
                }
                ftpClient.disconnect();
            }
        } catch (Exception e) {
            log.error("关闭ftp连接失败", e);
        }
    }

    /**
     * 进入到服务器的某个目录下
     *
     * @param directory
     */
    private static void changeWorkingDirectory(FTPClient ftpClient, String directory) throws Exception {
        try {
            if(directory.contains("\\")){
                directory = directory.replaceAll("\\\\","/");
            }
            String splitType = "/";
            ftpClient.changeWorkingDirectory(splitType);
            String[] subPathArray = directory.split(splitType);
            for (String subPath : subPathArray) {
                ftpClient.makeDirectory(subPath);
                ftpClient.changeWorkingDirectory(subPath);
            }
        } catch (IOException ioe) {
            log.error("改变ftp工作路径失败", ioe);
        }
    }

    /**
     * 转码[ISO-8859-1 -> GBK] 不同的平台需要不同的转码
     *
     * @param obj
     * @return ""
     */
    private static String iso8859togbk(Object obj) {
        try {
            if (obj == null) {
                return "";
            }
            return new String(obj.toString().getBytes("iso-8859-1"), "GBK");
        } catch (Exception e) {
            return "";
        }
    }

    public static Ftp getFtpUrlObj(String ftpIp, String ftpPort, String ftpUser, String ftpPassword) {
        Ftp ftpUrl = new Ftp();
        ftpUrl.setFtpIp(ftpIp);
        if (ftpPort != null) {
            ftpUrl.setFtpPort(Integer.parseInt(ftpPort));
        }
        ftpUrl.setFtpUsername(ftpUser);
        ftpUrl.setFtpPassword(ftpPassword);
        return ftpUrl;
    }


    /**
     * 读取ftp文件流
     * @param filePath
     * @return
     */
    public byte[] ftpReadImage(String filePath){
        byte[] fileByte = null;
        InputStream inputStream = null;
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        FTPClient ftpClient = connectServer();
        //1 测试连接
        if (null!=ftpClient) {
            try {
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
                inputStream = ftpClient.retrieveFileStream(new String(filePath.getBytes("UTF-8"), "iso-8859-1"));

                int readBytes;
                byte[] bytes = new byte[1024 * 1024];
                while ((readBytes = inputStream.read(bytes)) != -1) {
                    outputStream.write(bytes, 0, readBytes);
                }
                closeConnect(ftpClient);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                if(outputStream != null){
                    try {
                        outputStream.flush();
                        fileByte = outputStream.toByteArray();
                        outputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (inputStream != null){
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                closeConnect(ftpClient);
            }
        }
        return fileByte;
    }


}
