package com.gh.gamecenter.xapk

import android.os.Handler
import android.os.Looper
import com.gh.gamecenter.xapk.core.*
import com.gh.gamecenter.xapk.pi.IPackageInstaller
import java.util.concurrent.ExecutorService
import java.util.concurrent.Executors

class XApkUnZipper(
    private val outputFactory: XApkUnZipOutputFactory,
    private val executor: ExecutorService = Executors.newCachedThreadPool(),
    private val handler: Handler = Handler(Looper.getMainLooper()),
    private val useFlawToUnzip: Boolean = false
) : XApkUnZipTaskCallback {

    private val taskMap = mutableMapOf<String, XApkUnZipTask>()

    private val callbacks = mutableListOf<XApkUnZipCallback>()

    fun unzip(entry: XApkUnZipEntry) {
        if (taskMap.contains(entry.id)) {
            return
        }
        val task = XApkUnZipTask(
            id = entry.id,
            file = entry.file,
            isXapkApks = entry.isXapkApks,
            callback = this,
            useFlawToUnzip = useFlawToUnzip,
            factory = outputFactory
        )
        taskMap[entry.id] = task
        executor.execute(task)
    }

    fun cancel(id: String): Boolean {
        val task = taskMap[id] ?: return false
        task.cancel()
        return true
    }

    fun registerCallback(callback: XApkUnZipCallback) {
        if (callbacks.contains(callback)) {
            return
        }
        callbacks.add(callback)
    }

    fun unregisterCallback(callback: XApkUnZipCallback) {
        callbacks.remove(callback)
    }

    override fun onProgress(task: XApkUnZipTask, progress: Float) {
        handler.post {
            callbacks.forEach { it.onProgress(task.apk, progress) }
        }
    }

    override fun onSuccess(task: XApkUnZipTask, installer: IPackageInstaller) {
        taskMap.remove(task.id)
        handler.post {
            callbacks.forEach { it.onSuccess(task.apk, installer) }
        }
    }

    override fun onError(task: XApkUnZipTask, exception: Throwable) {
        taskMap.remove(task.id)
        handler.post {
            callbacks.forEach { it.onError(task.apk, exception) }
        }
    }

    override fun onCancel(task: XApkUnZipTask) {
        taskMap.remove(task.id)
        handler.post {
            callbacks.forEach { it.onCancel(task.apk) }
        }
    }

    override fun onNext(task: XApkUnZipTask, fileName: String) {
        handler.post {
            callbacks.forEach { it.onNext(task.apk, fileName) }
        }
    }
}