package com.duolebo.blyrobot.data

import android.content.Context
import android.util.Log
import com.duolebo.blyrobot.tools.FtpManager
import com.duolebo.blyrobot.util.AppUtil
import com.duolebo.blyrobot.util.Config
import net.gotev.uploadservice.*
import net.gotev.uploadservice.ftp.FTPUploadRequest
import net.gotev.uploadservice.ftp.UnixPermissions
import java.io.File
import java.util.*
import kotlin.collections.ArrayList

/**
 * 图片上传任务
 */
class ImageUploadTask {

    companion object {
        const val TAG = "RobotTaskUpload"
    }

    var packageName: String = ""
    var uploadImages = ArrayList<String>()
    var uploadId: String = ""
    var reUpload = false
    var isRunning = false

    private var context: Context
    private var uploadCheckTimer: Timer? = null
    private var isUploadChecking = false
    private var checkDelay = 5 * 60 * 1000L
    private var checkCount = 0

    constructor(context: Context) {
        this.context = context
    }

    fun from(task: Task) {
        this.packageName = task.apkInfo.packageName
        this.uploadImages.clear()
        this.uploadImages.addAll(task.uploadImages)
    }

    fun needReUpload(): Boolean {
        if (this.isRunning)
            return false

        if (!this.reUpload)
            return false

        if (isUploadRunning())
            return false

        if (this.isUploadChecking)
            return false

        return true
    }

    // 任务是否在上传队列中
    private fun isUploadRunning(): Boolean {
        val runningTaskIds = UploadService.getTaskList()
        if (this.uploadId in runningTaskIds)
            return true

        return false
    }

    fun start() {

        if (this.uploadImages.isEmpty()) {
            uploadTaskListener?.onComplete()
            return
        }

        this.isRunning = true
        Thread { uploadImage() }.start()

        // 预计每张图片上传时间是3秒
        startUploadCheck(3 * 1000L * this.uploadImages.size)
    }

    // 由于ftp库存在bug，这里启动一个定时器进行超时上传检测
    private fun startUploadCheck(delay: Long) {
        Log.i(TAG, "startUploadCheck with delay: $delay")
        this.checkDelay = delay
        uploadCheckTimer?.cancel()

        if (this.checkCount >= 3) {
            Log.i(TAG, "check time out, quit this job")
            uploadTaskListener?.onComplete()
            return
        }

        uploadCheckTimer = Timer()
        uploadCheckTimer!!.schedule(object : TimerTask() {
            override fun run() {
                checkUpload()
            }
        }, delay)

        this.checkCount++
    }

    private fun checkUpload() {
        Log.i(TAG, "check image upload")
        if (isUploadRunning()) {
            startUploadCheck(this.checkDelay / 3)
            return
        }

        this.isUploadChecking = true
        val lastUploadPos = getLastUploadImagePos()
        Log.i(TAG, "get last upload pos:$lastUploadPos")
        val size = this.uploadImages.size
        if (lastUploadPos >= size -1)
            return

        // 需要重新上传的图片
        val reUploadImages = this.uploadImages.subList(lastUploadPos, size - 1)
        this.uploadImages = ArrayList()
        this.uploadImages.addAll(reUploadImages)
        this.reUpload = true
        this.isUploadChecking = false
    }

    // 通过检查url是否存在找到最后上传图片的位置
    private fun getLastUploadImagePos(): Int {
        val res: Int
        val size = this.uploadImages.size
        var checkPos = size / 2
        var halfPos = checkPos
        while (true) {
            val exist = AppUtil.existsUrl(this.uploadImages[checkPos])
            if (exist) {
                checkPos += halfPos / 2
            } else {
                checkPos -= halfPos / 2
            }

            halfPos /= 2

            if (halfPos == 0) {
                res = if (exist)
                    checkPos
                else
                    checkPos - 1
                break
            }
        }

        return res
    }

    private fun uploadImage() {
        Log.i(TAG, "upload image....")
        try {
            val uploadRequest = FTPUploadRequest(context, Config.instance.getFtpServer(), 21)
                    .setUsernameAndPassword(Config.instance.getFtpUserName(), Config.instance.getFtpPassword())
                    .setNotificationConfig(UploadNotificationConfig())
                    .setCreatedDirectoriesPermissions(UnixPermissions("777"))
                    .setSocketTimeout(15000)
                    .setConnectTimeout(15000)
                    .setDelegate(uploadImageCallback())
                    .setMaxRetries(4)

            val unExistFiles = ArrayList<String>()
            this.uploadImages.forEach {
                val uploadFile = File(it)
                if (uploadFile.exists()) {
                    uploadRequest.addFileToUpload(it, Config.instance.getFtpRemotePath() + uploadFile.name)
                } else {
                    unExistFiles.add(it)
                }
            }

            // 删除不存在的图片记录
            if (!unExistFiles.isEmpty()) {
                this.uploadImages.removeAll(unExistFiles)
            }

            this.uploadId = uploadRequest.startUpload()
            Log.i(TAG, "upload id $uploadId")
        } catch (exc: Exception) {
            Log.e(TAG, exc.message, exc)
        }
    }

    private fun uploadComplete(errorCount: Int) {
        Log.i(TAG, "upload errorCount: $errorCount")
        uploadCheckTimer?.cancel()
        this.isRunning = false
        if (errorCount > 0 && errorCount > this.uploadImages.size / 3) {
            this.reUpload = true
        } else {
            // 上传完毕直接删除问题
            this.uploadImages.forEach {
                val uploadFile = File(it)
                if (uploadFile.exists()) {
                    uploadFile.delete()
                }
            }
        }

        uploadTaskListener?.onComplete()
    }

    /**
     * ftp 上传回调监听
     */
    private fun uploadImageCallback(): UploadStatusDelegate {
        val totalUpload = this.uploadImages.size
        Log.i(TAG, "total upload count : $totalUpload")

        return object : UploadStatusDelegate {
            override fun onCancelled(context: Context?, uploadInfo: UploadInfo?) {
                // empty
            }

            override fun onProgress(context: Context?, uploadInfo: UploadInfo?) {
                // empty
            }

            override fun onError(context: Context?, uploadInfo: UploadInfo?, serverResponse: ServerResponse?, exception: java.lang.Exception?) {
                val uploadSize = uploadInfo?.successfullyUploadedFiles!!.size
                Log.i(TAG, "onError...uploadCount: $uploadSize")
            }

            override fun onCompleted(context: Context?, uploadInfo: UploadInfo?, serverResponse: ServerResponse?) {
                val uploadSize = uploadInfo?.successfullyUploadedFiles!!.size
                Log.i(TAG, "onCompleted...uploadCount: $uploadSize")
                uploadComplete(totalUpload - uploadSize)
            }
        }
    }

    var uploadTaskListener: OnUploadTaskListener? = null

    /**
     * 图片上传任务状态
     */
    interface OnUploadTaskListener {
        fun onComplete()
    }
}