package com.easy.clean.ui.similar

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.airbnb.lottie.LottieAnimationView
import com.easy.clean.R
import com.easy.clean.base.BaseActivity
import com.easy.clean.base.LottieEnum
import com.easy.clean.bean.FeatureBean.Companion.SIMILAR_PHOTOS
import com.easy.clean.bean.SimilarBean
import com.easy.clean.business.ads.AdsMgr
import com.easy.clean.business.ads.AdsShowCallBack
import com.easy.clean.databinding.ActivitySimilarPhotosBinding
import com.easy.clean.databinding.ItemSimilarPhotosBinding
import com.easy.clean.databinding.ItemSimilarPhotosChildBinding
import com.easy.clean.ui.cleanresult.CleanResultActivity
import com.easy.clean.ui.dialog.ConfirmDialog
import com.easy.clean.ui.recyclebin.RecycleBinUtils
import com.easy.clean.utils.FileUtils
import com.easy.clean.utils.MediaUtils
import com.easy.clean.utils.Utils
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.CenterCrop
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import java.io.File
import java.util.concurrent.Semaphore

class SimilarPhotosActivity : BaseActivity<ActivitySimilarPhotosBinding>(ActivitySimilarPhotosBinding::inflate) {

    private val semaphore = Semaphore(20)
    private var state = 0
    private var list = mutableListOf<SimilarBean>()
    private var selectedFiles = listOf<SimilarBean>()
    private var total: Long = 0


    private val adapter by lazy {
        class ViewHolder(val binding: ItemSimilarPhotosBinding) : RecyclerView.ViewHolder(binding.root)

        object : RecyclerView.Adapter<ViewHolder>() {
            override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
                val binding = ItemSimilarPhotosBinding.inflate(LayoutInflater.from(parent.context), parent, false)
                return ViewHolder(binding)
            }

            override fun getItemCount(): Int = list.size

            override fun onBindViewHolder(holder: ViewHolder, position: Int) {
                val item = list[position]
                val total = item.items.filter { it.isSelect }.sumOf { it.size }
                holder.binding.tvSize.text = Utils.getSizeFormat(total)
                holder.binding.ivSelect.isSelected = item.items[0].isSelect

                val width = resources.displayMetrics.widthPixels
                val margin = resources.getDimensionPixelSize(R.dimen.dp_45)
                val imageWidth = (width - margin) / 4
                val largePhotoWidth = imageWidth * 2
                val largePhotoHeight = (largePhotoWidth * 0.92).toInt()
                holder.binding.ivFirstPhoto.layoutParams.width = largePhotoWidth
                holder.binding.ivFirstPhoto.layoutParams.height = largePhotoHeight

                val round = resources.getDimensionPixelSize(R.dimen.dp_8)
                val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
                Glide.with(holder.itemView.context)
                    .load(item.items[0].url)
                    .override(largePhotoWidth, largePhotoHeight)
                    .apply(options)
                    .into(holder.binding.ivFirstPhoto)
                holder.binding.ivFirstPhoto.setOnClickListener {
                    item.items[0].isSelect = !item.items[0].isSelect
                    holder.binding.ivSelect.isSelected = item.items[0].isSelect
                    updateView(holder, item)
                }

                val largePhotos = item.items.take(5)
                val largeAdapter = SimilarPhotosChildAdapter(largePhotos.subList(1, largePhotos.size)) {
                    updateView(holder, item)
                }
                holder.binding.rvLargePhoto.layoutManager =
                    GridLayoutManager(this@SimilarPhotosActivity, 2, GridLayoutManager.VERTICAL, false)
                holder.binding.rvLargePhoto.adapter = largeAdapter

                val photos = if (item.items.size > 4) item.items.subList(5, item.items.size) else mutableListOf()
                val adapter = SimilarPhotosChildAdapter(photos) { updateView(holder, item) }
                holder.binding.rvPhoto.layoutManager =
                    GridLayoutManager(this@SimilarPhotosActivity, 4, GridLayoutManager.VERTICAL, false)
                holder.binding.rvPhoto.adapter = adapter
            }

            private fun updateView(holder: ViewHolder, item: SimilarBean) {
                val total = item.items.filter { it.isSelect }.sumOf { it.size }
                holder.binding.tvSize.text = Utils.getSizeFormat(total)
                updateSelection()
            }
        }
    }

    inner class SimilarPhotosChildAdapter(
        var list: List<SimilarBean>,
        private val block: () -> Unit
    ) : RecyclerView.Adapter<SimilarPhotosChildAdapter.ViewHolder>() {
        inner class ViewHolder(val binding: ItemSimilarPhotosChildBinding) : RecyclerView.ViewHolder(binding.root)

        override fun onCreateViewHolder(
            parent: ViewGroup,
            viewType: Int
        ): ViewHolder {
            val binding = ItemSimilarPhotosChildBinding.inflate(LayoutInflater.from(parent.context), parent, false)
            return ViewHolder(binding)
        }

        override fun getItemCount(): Int = list.size

        override fun onBindViewHolder(holder: ViewHolder, position: Int) {
            val item = list[position]
            val width = holder.itemView.context.resources.displayMetrics.widthPixels
            val context = holder.itemView.context
            val margin = context.resources.getDimensionPixelSize(R.dimen.dp_45)
            val imageWidth = (width - margin) / 4
            val imageHeight = (imageWidth * 0.91).toInt()
            holder.binding.ivPhoto.layoutParams.width = imageWidth
            holder.binding.ivPhoto.layoutParams.height = imageHeight
            holder.binding.ivSelect.isSelected = item.isSelect
            holder.itemView.setOnClickListener {
                item.isSelect = !item.isSelect
                notifyItemChanged(position)
                block.invoke()
                updateSelection()
            }

            val round = context.resources.getDimensionPixelSize(R.dimen.dp_8)
            val options = RequestOptions().transform(CenterCrop(), RoundedCorners(round))
            Glide.with(holder.itemView.context)
                .load(item.url)
                .override(imageWidth, imageHeight)
                .apply(options)
                .into(holder.binding.ivPhoto)
        }
    }

    private fun updateSelection() {
        selectedFiles = list.flatMap { it.items.takeIf { it.isNotEmpty() }?.filter { it.isSelect } ?: emptyList() }
        total = selectedFiles.sumOf { it.size }
        showSelection(total > 0)
    }

    private fun showSelection(isSelection: Boolean) {
        binding.tvDelete.isEnabled = isSelection
        setTextSize(binding.tvDelete, getString(R.string.delete), total)
    }

    fun setTextSize(view: TextView, content: String, total: Long) {
        view.text = if (total > 0) "$content (${Utils.getSizeFormat(total)})" else content
    }


    override fun useDefaultImmersive() {
        setStatusBarColor()
        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()
        binding.llTitle.tvTitle.text=getString(R.string.similar_photos)
        binding.rvPhoto.adapter = adapter
        binding.rvPhoto.layoutManager = LinearLayoutManager(this)
        initData()
        showAdAnimation(LottieEnum.SIMILAR_PHOTOS_LOTTIE) {
            if (state != 0) scanComplete()
            state = 1

            AdsMgr.showNative(binding.flAd, R.layout.layout_admob_native_custom)
        }
    }

    private fun initData() {
        lifecycleScope.launch(Dispatchers.IO) {
            val images = MediaUtils.findImageFiles(this@SimilarPhotosActivity)
            val similarBeans = images.mapNotNull { value ->
                lifecycleScope.async(Dispatchers.IO) {
                    semaphore.acquire() // 请求许可
                    try {
                        SimilarUtils.createImage(value.path)
                    } finally {
                        semaphore.release() // 释放许可
                    }
                }.await()
            }
            val hasSame = mutableSetOf<String>()
            similarBeans.forEach { similar ->
                if (hasSame.contains(similar.url)) return@forEach
                hasSame.add(similar.url)
                similar.items.add(similar)
                similarBeans.forEach {
                    if (!hasSame.contains(it.url) && SimilarUtils.similarCondition(similar, it)) {
                        hasSame.add(it.url)
                        similar.items.add(it)
                    }
                }
            }
            list = similarBeans.filter { it.items.size > 1 }.toMutableList()
            launch(Dispatchers.Main) {
                if (state != 0) scanComplete()
                state = 2
            }
        }
    }

    private fun scanComplete() {
        binding.root.postDelayed({
            setSelectAll(true)
            stopAnimation()
        }, 2500)
    }

    fun stopAnimation() {
        val lottie: LottieAnimationView? = findViewById(R.id.lottie_animation)
        lottie?.clearAnimation()
        findViewById<View?>(R.id.layout_animation)?.visibility = View.GONE
        isBackDisable = false
    }

    override fun initListener() {
        super.initListener()

        binding.llTitle.ivBack.setOnClickListener { onBackPressedDispatcher.onBackPressed() }
        binding.ivSelect.setOnClickListener {
            it.isSelected = !it.isSelected
            setSelectAll(it.isSelected)
        }
        binding.tvDelete.setOnClickListener {
            if (selectedFiles.isEmpty()) return@setOnClickListener
            val dialog = ConfirmDialog(this)
            dialog.action = {
                AdsMgr.showInsert(this, showCallBack = object : AdsShowCallBack() {
                    override fun next() {
                        cleanSimilarBeans(selectedFiles)
                        CleanResultActivity.total = total
                        CleanResultActivity.functionKey = SIMILAR_PHOTOS
                        CleanResultActivity.titleName = getString(R.string.similar_photos)
                        goToAc(CleanResultActivity::class.java)
                    }
                })
            }
            dialog.showDialog("delete")
        }
    }

    @SuppressLint("NotifyDataSetChanged")
    private fun setSelectAll(isSelected: Boolean) {
        binding.ivSelect.isSelected = isSelected
        list.forEach { similar ->
            similar.items.forEachIndexed { index, similarBean ->
                similarBean.isSelect = isSelected
                if (isSelected && index == 0) {
                    similarBean.isSelect = false
                }
            }
        }
        adapter.notifyDataSetChanged()
        binding.ivSelect.setImageResource(if (isSelected) R.drawable.icon else R.drawable.icon_n)
        updateSelection()
    }

    fun AppCompatActivity.cleanSimilarBeans(list: List<SimilarBean>) {
        lifecycleScope.launch(Dispatchers.IO) {
            val paths = list.map { it.url }.toTypedArray()
            paths.forEach {
                RecycleBinUtils.addRecycleBinFile(File(it))
                FileUtils.deleteFile(it)
            }
            launch(Dispatchers.Main) { MediaUtils.updateMedia(applicationContext, paths) }
        }
    }

}