package com.base.scanqrclear.luma


import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.animation.ValueAnimator
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.animation.LinearInterpolator
import androidx.core.animation.doOnEnd
import androidx.core.view.updatePadding
import androidx.lifecycle.lifecycleScope
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.base.scanqrclear.R
import com.base.scanqrclear.databinding.FragmentHomeBinding
import com.base.scanqrclear.luma.AdmobHelps.KEY_INSTALL_TIME
import com.base.scanqrclear.luma.AppHelps.dpToPx
import com.base.scanqrclear.utils.BarUtils
import com.gyf.immersionbar.ktx.immersionBar
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import java.util.concurrent.TimeUnit

class HomeFragment : BaseFragment() {

    private val binding by lazy(LazyThreadSafetyMode.NONE) {
        FragmentHomeBinding.inflate(layoutInflater)
    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding.tvAppName.updatePadding(top = BarUtils.getStatusBarHeight())
        return binding.root
    }

    override fun onResume() {
        super.onResume()
        immersionBar {
            statusBarColor("#ef7246")
            statusBarDarkFont(true)
        }
    }
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        val functionAdapter = FunctionAdapter(getData(), true)
        functionAdapter.callback = object : BaseAdapter.OnClickCallback<FunctionBean> {
            override fun onClicked(view: View, position: Int, item: FunctionBean) {
                ActivityJumpHelps.start(requireContext(), launcher, item.name)
            }
        }
        binding.rvFunction.adapter = functionAdapter
        binding.rvFunction.layoutManager =
            GridLayoutManager(requireContext(), 3, GridLayoutManager.VERTICAL, false)

        val functionMoreAdapter = FunctionMoreAdapter(getMoreData())
        functionMoreAdapter.callback = object : BaseAdapter.OnClickCallback<FunctionBean> {
            override fun onClicked(view: View, position: Int, item: FunctionBean) {
                ActivityJumpHelps.start(requireContext(), launcher, item.name)
            }
        }
        binding.rvMore.adapter = functionMoreAdapter
        binding.rvMore.layoutManager = LinearLayoutManager(requireContext())
        binding.ivShan.setOnClickListener {
            ActivityJumpHelps.start(requireContext(), launcher, R.string.junk_scan)
        }
        binding.tvClean.setOnClickListener {
            ActivityJumpHelps.start(requireContext(), launcher, R.string.junk_scan)
        }
        binding.ivUpward.setOnClickListener {
            val targetY = binding.svNested.getChildAt(0).measuredHeight
            binding.svNested.smoothScrollTo(0, targetY)
        }
        startAnimation()
        initData()
        showDay()
    }

    private fun initData() {
        lifecycleScope.launch(Dispatchers.IO) {
            val totalStorage = async { AppHelps.getTotalExternalSize() }
            val availableStorage = async { AppHelps.getAvailableExternalSize() }
            val totalStorageSize = totalStorage.await()
            val availableStorageSize = availableStorage.await()
            val usedMemoryStorageSize = totalStorageSize - availableStorageSize
            val usedMemoryStorageScale = usedMemoryStorageSize * 100 / totalStorageSize

            val totalMemoryUsed = async { AppHelps.getMemTotal(requireContext()) }
            val availableMemoryUsed = async { AppHelps.getMemAvailable(requireContext()) }
            val totalMemoryUsedSize = totalMemoryUsed.await()
            val availableMemoryUsedSize = availableMemoryUsed.await()
            val usedMemoryUsedSize = totalMemoryUsedSize - availableMemoryUsedSize
            val usedMemoryUsedScale: Long = usedMemoryUsedSize * 100 / totalMemoryUsedSize
            withContext(Dispatchers.Main) {
                binding.tvStorageUsed.text = "${usedMemoryStorageScale.toInt()}%"
                binding.tvMemoryUsed.text = "${usedMemoryUsedScale.toInt()}%"
                binding.llStorageUsed.visibility = View.VISIBLE
                binding.llMemoryUsed.visibility = View.VISIBLE
                AnimationHelps.progress(binding.pbStorageUsed, usedMemoryStorageScale.toInt())
                AnimationHelps.progress(binding.pbMemoryUsed, usedMemoryUsedScale.toInt())
            }
        }
    }

    private fun showDay() {
        val installTime = SpUtils.getInstance().getLong(KEY_INSTALL_TIME)
        val result = calculateDaysBetween(installTime, System.currentTimeMillis())
        binding.tvDay.text = "${result.toInt()} ${getString(R.string.days)}"
    }

    fun calculateDaysBetween(timestamp1: Long, timestamp2: Long): Long {
        val diffInMillis = Math.abs(timestamp2 - timestamp1)
        val diffInDays = TimeUnit.MILLISECONDS.toDays(diffInMillis)
        return if (diffInDays < 1) 1 else diffInDays
    }

    private fun getData(): List<FunctionBean> {
        return mutableListOf<FunctionBean>().apply {
            add(FunctionBean(R.mipmap.icon_app_t, R.string.app_process))
            add(FunctionBean(R.mipmap.icon_junk_scan, R.string.junk_scan))
            add(FunctionBean(R.mipmap.icon_similar, R.string.similar_photos))
            add(
                FunctionBean(
                    R.mipmap.icon_whatsapp_clean_t,
                    R.string.whatsapp_clean
                )
            )

        }
    }

    private fun getMoreData(): List<FunctionBean> {
        return mutableListOf<FunctionBean>().apply {
            add(
                FunctionBean(
                    R.mipmap.icon_screenshots_1,
                    R.string.screenshot_clean
                )
            )
        }
    }

    private fun startAnimation() {
        binding.ivCircleBorder.visibility = View.GONE
        val delay: Long = 1200
        ValueAnimator.ofFloat(0f, 360f).apply {
            duration = delay
            interpolator = LinearInterpolator()
            addUpdateListener { animation ->
                val animatedValue = animation.animatedValue as Float
                binding.ivShan.rotation = animatedValue * 2
            }
            doOnEnd {
                binding.ivCircleBorder.visibility = View.VISIBLE
                AnimationHelps.rotation(binding.ivShan, 2000)
            }
        }.start()

        binding.tvJunkFiles.alpha = 0f
        ValueAnimator.ofFloat(0f, 1f).apply {
            this.duration = 1000
            this.startDelay = delay
            addUpdateListener { animation ->
                val value = animation.animatedValue as Float
                binding.tvJunkFiles.alpha = value
                binding.tvJunkFiles.translationY = (binding.tvClean.height * (1 - value))
            }
            start()
        }

        val scaleXAnim =
            ObjectAnimator.ofFloat(binding.ivCircleBorder, "scaleX", 0.85f, 1.35f).apply {
                duration = 2000
                startDelay = delay
                repeatCount = ValueAnimator.INFINITE
                repeatMode = ValueAnimator.RESTART
            }
        val scaleYAnim =
            ObjectAnimator.ofFloat(binding.ivCircleBorder, "scaleY", 0.85f, 1.35f).apply {
                duration = 2000
                startDelay = delay
                repeatCount = ValueAnimator.INFINITE
                repeatMode = ValueAnimator.RESTART
            }
        val alphaAnim = ObjectAnimator.ofFloat(binding.ivCircleBorder, "alpha", 0f, 1f).apply {
            duration = 2000
            startDelay = delay
            repeatCount = ValueAnimator.INFINITE
            repeatMode = ValueAnimator.RESTART
        }

        val widthAnim = ObjectAnimator.ofInt(binding.ivCircleBorder, "width", 1, 4).apply {
            duration = 2000
            startDelay = delay
            repeatCount = ValueAnimator.INFINITE
            repeatMode = ValueAnimator.RESTART
            addUpdateListener { animation ->
                val animatedValue = animation.animatedValue as Int
                binding.ivCircleBorder.setStrokeWidth(animatedValue)
            }
        }

        val animatorSet = AnimatorSet()
        animatorSet.playTogether(scaleXAnim, scaleYAnim, alphaAnim, widthAnim)
        animatorSet.start()

        val top = requireContext().dpToPx(5)
        ObjectAnimator.ofFloat(binding.ivUpward, "translationY", 0f, top).apply {
            duration = 1000
            repeatCount = ValueAnimator.INFINITE
            repeatMode = ValueAnimator.REVERSE
            start()
        }
    }
}