package com.lightinit.hsdataportal.common;
import com.lightinit.hsdataportal.json.pojo.FTPConfigurationParameter;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.*;
import org.springframework.stereotype.Component;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.SocketException;
import java.net.URLEncoder;

/**
 * Created by Mr.Yao on 2017/5/8.
 */
@Component
public class FTPTookitUtils {

    private FTPClient ftpClient;

    public FTPTookitUtils(){
        ftpClient=new FTPClient();
        this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
    }

    private boolean login(String url, int port, String username, String password) throws SocketException, IOException
    {
        int reply;
        ftpClient.connect(url, port);
        ftpClient.setControlEncoding("UTF-8");
        FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
        conf.setServerLanguageCode("zh");
        ftpClient.login(username, password);
        reply = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply))
        {
            ftpClient.disconnect();
            return false;
        }
        return true;
    }

    private void free()
    {
        if (ftpClient.isAvailable())
        {
            try
            {
                ftpClient.logout();
            } catch (IOException e)
            {
            }
        }
        if (ftpClient.isConnected())
        {
            try
            {
                ftpClient.disconnect();
            } catch (IOException e)
            {
            }
        }
    }
    public boolean uploadFile(InputStream input, String remoteAdr,FTPConfigurationParameter ftpconfig) throws IOException
    {
        boolean success = false;
        try
        {
            success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (!success)
            {
                return success;
            }
        } catch (IOException e)
        {
            return success;
        }
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        String remoteFileName = remoteAdr;
        if (remoteAdr.contains("/"))
        {
            remoteFileName = remoteAdr.substring(remoteAdr.lastIndexOf("/") + 1);
            String directory = remoteAdr.substring(0, remoteAdr.lastIndexOf("/") + 1);
            if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory))
            {
                int start = 0, end = 0;
                if (directory.startsWith("/"))
                {
                    start = 1;
                } else
                {
                    start = 0;
                }
                end = directory.indexOf("/", start);
                while (true)
                {
                    String subDirectory = remoteAdr.substring(start, end);
                    if (!ftpClient.changeWorkingDirectory(subDirectory))
                    {
                        if (ftpClient.makeDirectory(subDirectory))
                        {
                            ftpClient.changeWorkingDirectory(subDirectory);
                        } else
                        {
                            return false;
                        }
                    }
                    start = end + 1;
                    end = directory.indexOf("/", start);
                    if (end <= start)
                    {
                        break;
                    }
                }
            }
        }
        try
        {
            success = ftpClient.storeFile(remoteFileName, input);
            input.close();
        } catch (IOException e)
        {
            if (input != null)
            {
                input.close();
            }
        } finally
        {
            free();
        }
        return success;
    }

    public boolean uploadFile(String localAdr, String remoteAdr,FTPConfigurationParameter ftpconfig) throws IOException
    {
        boolean success = false;
        try
        {
            success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (!success)
            {
                return success;
            }
        } catch (IOException e)
        {
            return success;
        }
        ftpClient.enterLocalPassiveMode();
        ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        String remoteFileName = remoteAdr;
        if (remoteAdr.contains("/"))
        {
            remoteFileName = remoteAdr.substring(remoteAdr.lastIndexOf("/") + 1);
            String directory = remoteAdr.substring(0, remoteAdr.lastIndexOf("/") + 1);
            if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory))
            {
                int start = 0, end = 0;
                if (directory.startsWith("/"))
                {
                    start = 1;
                } else
                {
                    start = 0;
                }
                end = directory.indexOf("/", start);
                while (true)
                {
                    String subDirectory = remoteAdr.substring(start, end);
                    if (!ftpClient.changeWorkingDirectory(subDirectory))
                    {
                        if (ftpClient.makeDirectory(subDirectory))
                        {
                            ftpClient.changeWorkingDirectory(subDirectory);
                        } else
                        {
                            return false;
                        }
                    }
                    start = end + 1;
                    end = directory.indexOf("/", start);
                    if (end <= start)
                    {
                        break;
                    }
                }
            }
        }
        InputStream input = null;
        try
        {
            File f = new File(localAdr);
            //FTPFile[] fs = ftpClient.listFiles(remoteFileName);
            input = new FileInputStream(f);
            success = ftpClient.storeFile(remoteFileName, input);
            input.close();
        } catch (IOException e)
        {
            if (input != null)
            {
                input.close();
            }
        } finally
        {
            free();
        }
        return success;
    }

    public boolean deleteFile(String remoteAdr, String localAdr,FTPConfigurationParameter ftpconfig)
    {
        boolean success = false;
        try
        {
            success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (!success)
            {
                return success;
            }
            ftpClient.changeWorkingDirectory(remoteAdr);
            FTPFile[] fs = ftpClient.listFiles();
            if(fs.length>0)
            {
                success = ftpClient.removeDirectory(remoteAdr);
                ftpClient.logout();
            }
        } catch (IOException e)
        {
        } finally
        {
            free();
        }
        return success;
    }

    public boolean deleteDir(String remoteAdr,FTPConfigurationParameter ftpconfig)
    {
        boolean success = false;
        try
        {
            success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (!success)
            {
                return success;
            }
            ftpClient.changeWorkingDirectory(remoteAdr);
            FTPFile[] fs = ftpClient.listFiles();
            if(fs.length>0)
            {
                success = ftpClient.removeDirectory(remoteAdr);
                ftpClient.logout();
            }
        } catch (IOException e)
        {
        } finally
        {
            free();
        }
        return success;
    }

    public boolean downFile(String remoteremoteAdr, String localAdr, HttpServletResponse response,FTPConfigurationParameter ftpconfig)
    {
        boolean success = false;
        try
        {
            success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (!success)
            {
                return success;
            }
            ftpClient.changeWorkingDirectory(remoteremoteAdr);
            FTPFile[] fs = ftpClient.listFiles();

            for (FTPFile ftpFile : fs)
            {
                if (ftpFile.getName().equals(localAdr))
                {
                    response.setHeader("Content-disposition", "attachment;localAdr=" + URLEncoder.encode(localAdr, "UTF-8"));
                    File f=new File(localAdr);
                    OutputStream os=new FileOutputStream(f);
                    ftpClient.retrieveFile(new String(ftpFile.getName().getBytes("UTF-8"), "ISO-8859-1"), os);
                    os.flush();
                    os.close();
                }
            }
            ftpClient.logout();
            success = true;
        } catch (IOException e)
        {
            e.printStackTrace();
        } finally
        {
            free();
        }
        return success;
    }

    public String readFileContent(String remoteremoteAdr, String localAdr,FTPConfigurationParameter ftpconfig)
    {
        String content = null;
        try
        {
            boolean success = login(ftpconfig.getHost(), ftpconfig.getPort(), ftpconfig.getUsername(),ftpconfig.getPassword());
            if (success)
            {
                ftpClient.changeWorkingDirectory(remoteremoteAdr);
                FTPFile[] fs = ftpClient.listFiles();
                for (FTPFile ftpFile : fs)
                {
                    if (ftpFile.getName().equals(localAdr))
                    {
                        File f=new File(localAdr);
                        ftpClient.retrieveFile(new String(ftpFile.getName().getBytes("UTF-8"), "ISO-8859-1"), new FileOutputStream(f));
                        ByteArrayOutputStream bos = new ByteArrayOutputStream();
                        ftpClient.retrieveFile(ftpFile.getName(), bos);
                        bos.flush();
                        bos.close();
                        content = new String(bos.toByteArray(), "UTF-8");
                    }
                }
            }
        } catch (IOException e)
        {
        } finally
        {
            free();
        }
        return content;
    }

    public static boolean isDirExist(String localAdr, FTPFile[] fs)
    {
        for (FTPFile ftpFile : fs)
        {
            if (ftpFile.getName().equals(localAdr))
            {
                return true;
            }
        }
        return false;
    }

    public static String changeName(String localAdr, FTPFile[] fs)
    {
        int n = 0;
        StringBuffer localAdr_ = new StringBuffer("");
        localAdr_ = localAdr_.append(localAdr);
        while (isDirExist(localAdr_.toString(), fs))
        {
            n++;
            String a = "[" + n + "]";
            int b = localAdr_.lastIndexOf(".");
            int c = localAdr_.lastIndexOf("[");
            if (c < 0)
            {
                c = b;
            }
            StringBuffer name = new StringBuffer(localAdr_.substring(0, c));
            StringBuffer suffix = new StringBuffer(localAdr_.substring(b + 1));
            localAdr_ = name.append(a).append(".").append(suffix);
        }
        return localAdr_.toString();
    }
}
