package com.doverfuelingsolutions.issp.api.ftp

import com.wayne.www.waynelib.util.log.DFSLog
import com.doverfuelingsolutions.issp.utils.thread.ThreadUtil
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.apache.commons.net.ftp.FTPClient
import org.apache.commons.net.ftp.FTPReply
import java.io.File
import java.util.*
import kotlin.coroutines.resume
import kotlin.coroutines.suspendCoroutine

/**
 * Wayne FTP客户端工具类
 *
 * @param host     FTP服务器域名或者IP地址
 * @param username 账号
 * @param password 密码
 */
class WayneFTPClient(private val host: String, private val username: String, private val password: String) {

    private val clientFTP = FTPClient()
    private var isConnected = false

    /**
     * 「协程挂起函数」连接登录到FTP服务器
     *
     * @return 连接是否成功
     */
    suspend fun connect() = suspendCoroutine<Boolean> {
        ThreadUtil.io {
            try {
                clientFTP.connect(host)
                if (!FTPReply.isPositiveCompletion(clientFTP.replyCode)) {
                    it.resume(false)
                    return@io
                }

                val success = clientFTP.login(username, password)
                if (!success) {
                    it.resume(false)
                    clientFTP.disconnect()
                    return@io
                }

                isConnected = true
                it.resume(true)
            } catch (e: Exception) {
                DFSLog.e(e)
            }
        }
    }

    /**
     * 「协程挂起函数」上传文件到FTP服务器，如果没有连接则自动连接
     *
     * @param file 待上传的本地文件
     * @param remoteFolder 上传文件的服务器目录
     * @param fileType 文件类型，默认值是 FTPClient.BINARY_FILE_TYPE（二进制），其他可选：FTPClient.ASCII_FILE_TYPE（文本）、FTPClient.EBCDIC_FILE_TYPE、FTPClient.LOCAL_FILE_TYPE
     */
    suspend fun uploadFile(file: File, remoteFolder: String, fileType: Int = FTPClient.BINARY_FILE_TYPE) = suspendCoroutine<Boolean> {
        GlobalScope.launch {
            if (!isConnected && !connect()) {
                it.resume(false)
                return@launch
            }

            ThreadUtil.io {
                clientFTP.setFileType(fileType)
                clientFTP.makeDirectory(remoteFolder)
                val resultChangeDirectory = clientFTP.changeWorkingDirectory(remoteFolder)
                if (!resultChangeDirectory) {
                    it.resume(false)
                    DFSLog.e("FTP服务器目录「$remoteFolder」创建失败")
                    close()
                    return@io
                }
                val inputStream = file.inputStream()
                try {
                    val resultAppend = clientFTP.appendFile(file.name, inputStream)
                    it.resume(resultAppend)
                } catch (e: Exception) {
                    it.resume(false)
                    DFSLog.e(e)
                } finally {
                    inputStream.close()
                }
            }
        }
    }

    /**
     * 「协程挂起函数」上传文件到FTP服务器，如果没有连接则自动连接
     *
     * @param filePath 待上传的本地文件路径
     * @param remoteFolder 上传文件的服务器目录
     * @param fileType 文件类型，默认值是 FTPClient.BINARY_FILE_TYPE（二进制），其他可选：FTPClient.ASCII_FILE_TYPE（文本）、FTPClient.EBCDIC_FILE_TYPE、FTPClient.LOCAL_FILE_TYPE
     */
    suspend fun uploadFile(filePath: String, remoteFolder: String, fileType: Int = FTPClient.BINARY_FILE_TYPE) = uploadFile(File(filePath), remoteFolder, fileType)

    /**
     * 关闭FTP客户端
     */
    fun close() {
        isConnected = false
        clientFTP.disconnect()
    }
}