package com.base.browserwhite.ui.activity.cleanjunk

import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.drawable.Drawable
import android.os.Environment
import android.view.View
import android.view.animation.AccelerateInterpolator
import android.view.animation.LinearInterpolator
import androidx.activity.addCallback
import androidx.core.content.ContextCompat
import androidx.lifecycle.lifecycleScope
import com.base.browserwhite.MyApplication
import com.base.browserwhite.R
import com.base.browserwhite.ads.AdmobMaxHelper
import com.base.browserwhite.bean.ChildBean
import com.base.browserwhite.bean.ConstObject
import com.base.browserwhite.bean.ParentBean
import com.base.browserwhite.databinding.ActivityScanJunkBinding
import com.base.browserwhite.ui.activity.BaseActivity
import com.base.browserwhite.ui.activity.result.ResultActivity
import com.base.browserwhite.ui.adapter.JunkExpandAdapter
import com.base.browserwhite.ui.adapter.JunkScanAdapter
import com.base.browserwhite.utils.BarUtils
import com.base.browserwhite.utils.FileHelp.getFileFolder
import com.base.browserwhite.utils.KotlinExt.toFormatSize
import com.base.browserwhite.utils.MediaStoreUtils.queryFiles
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.SharedFlow
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import java.io.File
import kotlin.random.Random


class ScanJunkActivity : BaseActivity<ActivityScanJunkBinding>() {

    private lateinit var junkScanAdapter: JunkScanAdapter
    private lateinit var junkExpandAdapter: JunkExpandAdapter

    override val binding: ActivityScanJunkBinding by lazy {
        ActivityScanJunkBinding.inflate(layoutInflater)
    }
    private val mPathFlow = MutableSharedFlow<String>(
        replay = 5,//当新的订阅者Collect时，发送几个已经发送过的数据给它
        extraBufferCapacity = 5,//减去replay，MutableSharedFlow还缓存多少数据,缓冲池容量 = replay + extraBufferCapacity
        onBufferOverflow = BufferOverflow.DROP_OLDEST//缓存策略，三种 丢掉最新值、丢掉最旧值和挂起
    )
    private val pathFlow: SharedFlow<String> = mPathFlow

    private var cleanSize: Long = 0L

    @SuppressLint("SetTextI18n")
    override fun initView() {
        BarUtils.setStatusBarLightMode(this, true)
        BarUtils.setStatusBarColor(this, Color.TRANSPARENT)
//        binding.root.updatePadding(top = BarUtils.getStatusBarHeight())


        junkScanAdapter = JunkScanAdapter()
        binding.rv.adapter = junkScanAdapter

        junkExpandAdapter = JunkExpandAdapter { size ->
            cleanSize = size
            if (size > 0) {
                binding.tvBtn.text = "Clean up ${size.toFormatSize()}"
            } else {
                binding.tvBtn.text = "Got it"
            }
        }
        binding.rvEx.adapter = junkExpandAdapter

        lifecycleScope.launch(Dispatchers.Main) {
            pathFlow.collectLatest {
                binding.tvPath.text = it
            }
        }
        beginScan()
    }

    override fun initListener() {
        super.initListener()

        onBackPressedDispatcher.addCallback {
            AdmobMaxHelper.admobMaxShowInterstitialAd(this@ScanJunkActivity, false) {
                finishToMain()
            }
        }
        binding.flFanhui.setOnClickListener {
            onBackPressedDispatcher.onBackPressed()
        }

        binding.tvBtn.setOnClickListener {
            if (binding.tvBtn.text == "Got it") {
                startActivity(Intent(this, ResultActivity::class.java).apply {
                    putExtra("from", ConstObject.JUNK_CLEANER)
                })
                finish()
            } else {
                startActivity(Intent(this, CleaningActivity::class.java).apply {
                    val list = junkExpandAdapter.getChoosePath()
                    putExtra("list", list.toTypedArray())
                    putExtra("size", cleanSize)
                })
                finish()
            }
        }
    }

    @SuppressLint("SetTextI18n")
    private fun beginScan() = lifecycleScope.launch(Dispatchers.Main) {
        var size = 0L
        junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Residual File"), 0)
        delay(Random.nextLong(500, 1500))
        junkScanAdapter.addData(ParentBean(R.mipmap.x_useless, "Useless installation package"), 1)
        delay(Random.nextLong(500, 1500))
        junkScanAdapter.addData(ParentBean(R.mipmap.x_temp, "Temp Files"), 2)
        delay(Random.nextLong(500, 1500))
        junkScanAdapter.addData(ParentBean(R.mipmap.x_residual, "Log Files"), 3)

        val emptyFolder = arrayListOf<File>()
        arrayOf(
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
            Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
        ).forEach { dir ->
            val list = getFileFolder(mPathFlow, dir, filter = { it.listFiles().isNullOrEmpty() }).await()
            emptyFolder.addAll(list)
        }
        size = emptyFolder.sumOf { it.length() }
        setSize(size)
        junkScanAdapter.setFinishScan(0)

        val apkList = queryFiles(this@ScanJunkActivity, ".apk", mPathFlow).await()
        size += apkList.sumOf { it.length() }
        setSize(size)
        junkScanAdapter.setFinishScan(1)

        val tempList = queryFiles(this@ScanJunkActivity, ".temp", mPathFlow).await()
        size += tempList.sumOf { it.length() }
        setSize(size)
        junkScanAdapter.setFinishScan(2)

        val logList = queryFiles(this@ScanJunkActivity, ".log", mPathFlow).await()
        size += logList.sumOf { it.length() }
        setSize(size)
        junkScanAdapter.setFinishScan(3)

        delay(Random.nextLong(500, 1000))


        binding.rv.visibility = View.GONE
        binding.rvEx.visibility = View.VISIBLE
//        if (emptyFolder.isNotEmpty()) {
        val childList1 = emptyFolder.map { ChildBean(R.mipmap.d_reseiual, it.absolutePath) }
        val emptyParent = ParentBean(tittle = "Residual File", childItem = childList1)
        junkExpandAdapter.addData(listOf(emptyParent), false)
        junkExpandAdapter.expandAllGroup()
//        }

        if (apkList.isNotEmpty()) {
            val childList2 = apkList.map {
                ChildBean(R.mipmap.d_useless, it.absolutePath).apply { apkIcon = getApkDrawable(it.absolutePath) }
            }
            val apkParent = ParentBean(tittle = "Useless installation package", childItem = childList2)
            junkExpandAdapter.addData(listOf(apkParent), false)
            junkExpandAdapter.expandAllGroup()
        }

        if (tempList.isNotEmpty()) {
            val childList3 = tempList.map { ChildBean(R.mipmap.d_temp, it.absolutePath) }
            val tempParent = ParentBean(tittle = "Temp Files", childItem = childList3)
            junkExpandAdapter.addData(listOf(tempParent), false)
            junkExpandAdapter.expandAllGroup()
        }
        if (logList.isNotEmpty()) {
            val childList4 = logList.map { ChildBean(R.mipmap.d_log, it.absolutePath) }
            val logParent = ParentBean(tittle = "Log Files", childItem = childList4)
            junkExpandAdapter.addData(listOf(logParent), false)
            junkExpandAdapter.expandAllGroup()
        }

        binding.progressBar.visibility = View.GONE
        binding.clTop.setBackgroundResource(R.mipmap.hong_bg)
        binding.tvPath.visibility = View.GONE
        binding.tvBtn.isEnabled = true
        binding.tvBtn.setTextColor(ContextCompat.getColor(this@ScanJunkActivity, R.color.white))
        cleanSize = size

        if (size > 0) {
            binding.tvBtn.text = "Clean up ${size.toFormatSize()}"
        } else {
            binding.tvBtn.text = "Got it"
        }

    }

    private fun setSize(size: Long) {
        val split = size.toFormatSize().split(" ")
        binding.tvSize.text = split[0]
        binding.tvUnit.text = split[1]
    }

    private fun getApkDrawable(apkPath: String): Drawable? {
        val packageInfo = packageManager.getPackageArchiveInfo(apkPath, PackageManager.GET_ACTIVITIES)
        if (packageInfo != null) {
            val applicationInfo = packageInfo.applicationInfo
            return packageManager.getApplicationIcon(applicationInfo)
        }
        return null
    }

    companion object {
        fun fastGetJunkSize(context: Context = MyApplication.context): Long {
            var size = 0L
            val emptyFolder = arrayListOf<File>()
            arrayOf(
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM),
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS),
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES),
                Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC),
            ).forEach { dir ->
                val list = getFileFolder(dir, filter = { it.listFiles().isNullOrEmpty() })
                emptyFolder.addAll(list)
            }
            size = emptyFolder.sumOf { it.length() }

            val apkList = queryFiles(context, ".apk")
            size += apkList.sumOf { it.length() }

            val tempList = queryFiles(context, ".apk")
            size += tempList.sumOf { it.length() }

            val logList = queryFiles(context, ".apk")
            size += logList.sumOf { it.length() }
            return size
        }
    }

}