package com.tgv.malware.ui.clean

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.content.ContextCompat
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.LinearLayoutManager
import com.tgv.malware.R
import com.tgv.malware.base.BaseActivity
import com.tgv.malware.base.LottieEnum
import com.tgv.malware.base.cleanFileBeans
import com.tgv.malware.bean.FeatureBean.Companion.JUNK_CLEAN
import com.tgv.malware.bean.FeatureBean.Companion.setFunctionTodayUsed
import com.tgv.malware.bean.FileBean
import com.tgv.malware.business.ads.AdsMgr
import com.tgv.malware.databinding.ActivityJunkCleanBinding
import com.tgv.malware.databinding.ItemJunkCleanChildBinding
import com.tgv.malware.databinding.ItemJunkCleanGroupBinding
import com.tgv.malware.ui.cleanresult.CleanResultActivity
import com.tgv.malware.utils.FileUtils
import com.tgv.malware.utils.MediaUtils
import com.tgv.malware.utils.MineTypeUtils
import com.tgv.malware.utils.MyAnimationUtils
import com.tgv.malware.utils.Utils
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import pokercc.android.expandablerecyclerview.ExpandableAdapter
import pokercc.android.expandablerecyclerview.ExpandableItemAnimator
import kotlin.random.Random


class JunkCleanActivity : BaseActivity<ActivityJunkCleanBinding>(ActivityJunkCleanBinding::inflate) {

    private var isStartAnimation = true
    private var list = mutableListOf<FileBean>()
    private var total: Long = 0
    private var selectedFiles = listOf<FileBean>()

    private val adapter by lazy {
        class ChildViewHolder(val binding: ItemJunkCleanChildBinding) : ExpandableAdapter.ViewHolder(binding.root)
        class GroupViewHolder(val binding: ItemJunkCleanGroupBinding) : ExpandableAdapter.ViewHolder(binding.root)

        object : ExpandableAdapter<ExpandableAdapter.ViewHolder>() {
            override fun getChildCount(groupPosition: Int): Int = list[groupPosition].items.size

            override fun getGroupCount(): Int = list.size

            override fun onCreateChildViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
                val binding = ItemJunkCleanChildBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
                return ChildViewHolder(binding)
            }

            override fun onCreateGroupViewHolder(viewGroup: ViewGroup, viewType: Int): ViewHolder {
                val binding = ItemJunkCleanGroupBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
                return GroupViewHolder(binding)
            }

            override fun onGroupViewHolderExpandChange(
                holder: ViewHolder,
                groupPosition: Int,
                animDuration: Long,
                expand: Boolean
            ) {
            }

            override fun onBindGroupViewHolder(
                holder: ViewHolder,
                groupPosition: Int,
                expand: Boolean,
                payloads: List<Any>
            ) {
                holder as GroupViewHolder
                val group = list[groupPosition]
                holder.binding.tvName.text = group.name
                holder.binding.tvLength.text = Utils.getSizeFormat(group.length)
                holder.binding.ivIcon.setImageResource(group.icon)
                holder.binding.ivIndicator.setImageResource(if (expand) R.drawable.icon_up else R.drawable.icon_down)
                holder.binding.clItem.setBackgroundResource(if (expand && group.items.isNotEmpty()) R.drawable.white_background_top_8 else R.drawable.white_background_8)
                holder.binding.ivSelect.isSelected = group.isSelected
                holder.binding.ivSelect.setOnClickListener {
                    group.isSelected = !group.isSelected
                    group.items.forEach { it.isSelected = group.isSelected }
                    notifyGroupChange(groupPosition)
                    for (childPosition in 0..<group.items.size) {
                        notifyChildChange(groupPosition, childPosition)
                    }
                    updateSelection()
                }

                if (isStartAnimation) {
                    val translationX = holder.itemView.context.resources.displayMetrics.widthPixels.toFloat()
                    holder.itemView.translationX = -translationX
                    MyAnimationUtils.translationX(holder.itemView, -translationX, 0f, 1000, (groupPosition + 1) * 300L)
                }
                if (groupPosition == list.size - 1) isStartAnimation = false
            }

            override fun onBindChildViewHolder(
                holder: ViewHolder,
                groupPosition: Int,
                childPosition: Int,
                payloads: List<Any>
            ) {
                holder as ChildViewHolder
                val group = list[groupPosition]
                val child = group.items[childPosition]
                holder.binding.tvName.text = child.name
                holder.binding.tvLength.text = Utils.getSizeFormat(child.length)
                holder.itemView.setBackgroundResource(if (childPosition == group.items.size - 1) R.drawable.white_background_bottom_8 else R.color.white)
                holder.binding.ivSelect.isSelected = child.isSelected
                holder.itemView.setOnClickListener {
                    child.isSelected = !child.isSelected
                    notifyChildChange(groupPosition, childPosition)
                    val isSelected = group.items.stream().allMatch(FileBean::isSelected)
                    if (group.isSelected != isSelected) {
                        group.isSelected = isSelected
                        notifyGroupChange(groupPosition)
                    }
                    updateSelection()
                }
            }
        }
    }

    private fun updateSelection() {
        selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelected } ?: emptyList() }
        total = selectedFiles.sumOf { it.length }
        setClean()
    }

    private fun setClean() {
        binding.tvClean.text =
            if (total > 0) "${getString(R.string.clean)} (${Utils.getSizeFormat(total)})" else getString(R.string.go_it)
        binding.tvClean.isEnabled = total > 0
        if (binding.tvClean.isEnabled) {
            binding.tvClean.setTextColor(ContextCompat.getColor(this, R.color.white))
        } else {
            binding.tvClean.setTextColor(ContextCompat.getColor(this, R.color.colorPrimary))
        }
    }

    override fun useDefaultImmersive() {
        ViewCompat.setOnApplyWindowInsetsListener(binding.root) { v, insets ->
            val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
            v.setPadding(systemBars.left, 0, systemBars.right, systemBars.bottom)
            binding.clTop.setPadding(0, systemBars.top, 0, 0)
            insets
        }
    }

    override fun initView() {
        super.initView()
        AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
        binding.expandableFiles.adapter = adapter
        binding.expandableFiles.layoutManager = LinearLayoutManager(this)
        binding.expandableFiles.itemAnimator = ExpandableItemAnimator(binding.expandableFiles)

        initData()

        setFunctionTodayUsed(JUNK_CLEAN)
    }

    override fun initListener() {
        super.initListener()

        binding.ivBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
        binding.tvClean.setOnClickListener {
            if (isBackDisable) return@setOnClickListener

            if (total > 0) {
                showAdAnimation(LottieEnum.CLEAN_LOTTIE) {
                    cleanFileBeans(selectedFiles)

                    CleanResultActivity.functionKey = JUNK_CLEAN
                    CleanResultActivity.titleName = this@JunkCleanActivity.getString(R.string.junk_clean)
                    CleanResultActivity.total = total
                    goToAc(CleanResultActivity::class.java)
                    finish()
                }
            } else {
                goToAc(CleanResultActivity::class.java)
            }

        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun initData() {
        isBackDisable = true
        binding.tvPath.text = ""
        binding.tvClean.visibility = View.GONE
        lifecycleScope.launch(Dispatchers.IO) {
            val emptyFolders = async { FileUtils.findEmptyFolders() }.await()
            val files = async { MediaUtils.findSpecifiedFiles(this@JunkCleanActivity) }.await()
            emptyFolders.forEach { it.isSelected = true }
            files.forEach { it.isSelected = true }

            val apkFiles = files.filter { file ->
                MineTypeUtils.apks.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()
            val tempFiles = files.filter { file ->
                MineTypeUtils.temps.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()
            val logsFiles = files.filter { file ->
                MineTypeUtils.logs.any { suffix -> file.name.endsWith(suffix, true) }
            }.toMutableList()

            list = getGroupData()
            list[0].length = emptyFolders.sumOf { it.length }
            list[1].length = apkFiles.sumOf { it.length }
            list[2].length = tempFiles.sumOf { it.length }
            list[3].length = logsFiles.sumOf { it.length }
            list[0].items = emptyFolders
            list[1].items = apkFiles
            list[2].items = tempFiles
            list[3].items = logsFiles
            total = list.sumOf { it.length }
            val childData = mutableListOf<FileBean>().apply {
                addAll(emptyFolders)
                addAll(apkFiles)
                addAll(tempFiles)
                addAll(logsFiles)
            }
            val list = childData.sortedByDescending { it.length }
            val totalSize = list.sumOf { it.length }
            val random = Random.nextLong(2500, 3000)
            launch(Dispatchers.Main) {
                MyAnimationUtils.progress(binding.pbProgress, 0, 100, random)
                ValueAnimator.ofFloat(0f, totalSize.toFloat()).apply {
                    duration = random
                    interpolator = LinearInterpolator()
                    addUpdateListener { animation ->
                        val value = animation.animatedValue as Float
                        setSize(value.toLong())
                    }
                }.start()
            }
            for (data in list) {
                if (binding.pbProgress.progress == 100) break
                withContext(Dispatchers.Main) {
                    binding.tvPath.text = data.path
                }
            }
            delay(random)
            launch(Dispatchers.Main) {
                scanComplete()
                adapter.notifyDataSetChanged()
            }
        }
    }

    private fun getGroupData(): MutableList<FileBean> {
        return mutableListOf(
            FileBean(getString(R.string.empty_folder), icon = R.drawable.icon_empty, isSelected = true),
            FileBean(getString(R.string.apk_files), icon = R.drawable.icon_apk, isSelected = true),
            FileBean(getString(R.string.temp_files), icon = R.drawable.temp, isSelected = true),
            FileBean(getString(R.string.logs_files), icon = R.drawable.icon_log, isSelected = true),
        )
    }

    private fun scanComplete() {
        isBackDisable = false
        binding.expandableFiles.visibility = View.VISIBLE
        binding.tvClean.visibility = View.VISIBLE
        binding.tvPath.text = getString(R.string.clean_tips)
        updateSelection()
    }

    private fun setSize(size: Long) {
        val values = Utils.getSizeArray(size)
        binding.tvLength.text = values[0]
        binding.tvUnit.text = values[1]
    }

}