package com.offline.music.task.player.ui.activity

import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.widget.Toast
import androidx.annotation.OptIn
import androidx.media3.common.Player
import androidx.media3.common.util.UnstableApi
import com.bumptech.glide.Glide
import com.google.android.material.slider.Slider.OnChangeListener
import com.gyf.immersionbar.ktx.immersionBar
import com.offline.music.task.player.R
import com.offline.music.task.player.databinding.ActivityPlayDetailsBinding
import com.offline.music.task.player.db.bean.Audio
import com.offline.music.task.player.tools.util.containsContent
import com.offline.music.task.player.tools.util.convertMillisToMinutesAndSecondsString
import com.offline.music.task.player.tools.util.getAudioDurationFromAssets
import com.offline.music.task.player.tools.media.MediaControllerManager

class PlayerActivity : BaseActivity() {

    companion object {
        const val KEY_DETAILS_AUDIO = "key_details_audio"
    }

    private lateinit var binding: ActivityPlayDetailsBinding
    private var audio: Audio? = null
    private var rotationAnimator: ValueAnimator? = null


    @SuppressLint("ForegroundServiceType")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityPlayDetailsBinding.inflate(layoutInflater)
        setContentView(binding.root)
        initImmersionBar()
        audio = intent.getSerializableExtra(KEY_DETAILS_AUDIO) as Audio?
        if (audio == null) {
            onBackPressed()
            Toast.makeText(this, getString(R.string.data_error), Toast.LENGTH_SHORT).show()
        }
        initView()

    }

    private fun initImmersionBar() {
        immersionBar {
            statusBarDarkFont(false)
            statusBarView(binding.view)
        }
    }

    @OptIn(UnstableApi::class)
    private fun initView() {

        if (audio?.image?.isNotEmpty() == true) {
            Glide.with(this)
                .load("file:///android_asset/${audio?.image}")
                .into(binding.image)
        } else {
            binding.image.setImageResource(R.mipmap.default_list_img)
        }
        binding.seekBar.value = 0f
        binding.nameTv.text = audio?.name
        binding.descTv.text = audio?.name

        if (containsContent(audio?.file!!)) {
            binding.totalDurationTv.text = convertMillisToMinutesAndSecondsString(audio?.duration!!)
            binding.seekBar.valueTo = audio?.duration!!.toFloat()
        } else {
            val s = getAudioDurationFromAssets(this, audio?.file!!)
            binding.totalDurationTv.text = convertMillisToMinutesAndSecondsString(s)

            binding.seekBar.valueTo = s.toFloat()
        }

        binding.backBtn.setOnClickListener {
            onBackPressed()
        }

        val currentPlayer = MediaControllerManager.getController()
        currentPlayer?.addListener(object : Player.Listener {
            override fun onPlayWhenReadyChanged(
                playWhenReady: Boolean,
                reason: Int
            ) {
                updatePlayState(playWhenReady, "playWhenReady")
                updateProgressState()
            }

            override fun onPlaybackStateChanged(playbackState: Int) {
                updateProgressState()
            }
        })
        binding.playImg.setOnClickListener {
            if (currentPlayer != null) {
                if (currentPlayer.isPlaying) {
                    currentPlayer.pause()
                    updatePlayState(false, "click")
                } else {
                    currentPlayer.play()
                    updatePlayState(true, "click")
                }
                updateProgressState()
            }
        }
        MediaControllerManager.setupMedia(this,
            audio!!,
            object : Player.Listener {
                override fun onPlayWhenReadyChanged(
                    playWhenReady: Boolean,
                    reason: Int
                ) {
                    updatePlayState(playWhenReady, "playWhenReady")
                    updateProgressState()
                }

                override fun onPlaybackStateChanged(playbackState: Int) {
                    updateProgressState()
                }
            })

        binding.seekBar.addOnChangeListener(OnChangeListener { slider, value, fromUser ->
            if (fromUser) {
                if (currentPlayer != null) {
                    currentPlayer.seekTo(value.toLong())
                    val ss = currentPlayer.isPlaying
                    if (!ss) {
                        currentPlayer.play()
                    }
                }
            }
        })
    }

    override fun onResume() {
        super.onResume()
        val currentPlayer = MediaControllerManager.getController()
        if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY) {
            val isPlaying = currentPlayer.isPlaying
            updatePlayState(isPlaying, "onResume")
            if (isPlaying) {
                updateProgressState()
            } else {
                val currentPosition = currentPlayer.currentPosition
                val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
                binding.progressDurationTv.text = currentString
                binding.seekBar.value = currentPosition.toFloat()
            }
        }
    }

    private fun updatePlayState(b: Boolean, string: String) {
        if (b) {
            binding.playImg.setImageResource(R.drawable.playing_green_icon)
        } else {
            binding.playImg.setImageResource(R.drawable.details_play_icon)
        }
    }

    override fun onPause() {
        super.onPause()
        finishWithAnimation()
    }

    override fun onBackPressed() {
        super.onBackPressed()
    }

    private fun finishWithAnimation() {
        overridePendingTransition(R.anim.no_animation, R.anim.slide_down)
        Handler(Looper.getMainLooper()).postDelayed({
            finish()
        }, 500)
    }

    override fun onDestroy() {
        super.onDestroy()
        progressHandler.removeCallbacksAndMessages(null)
        rotationAnimator?.cancel()
    }

    private fun updateProgressState() {
        val currentPlayer = MediaControllerManager.getController()
        if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
            updatePlayState(currentPlayer.isPlaying, "playWhenReady")
            progressHandler.removeCallbacksAndMessages(null)
            progressHandler.sendEmptyMessage(1)
        } else {
            progressHandler.removeCallbacksAndMessages(null)
        }
    }

    private val progressHandler = object : Handler(Looper.myLooper()!!) {
        override fun handleMessage(msg: Message) {
            val currentPlayer = MediaControllerManager.getController()
            if (currentPlayer != null && currentPlayer.playbackState == Player.STATE_READY && currentPlayer.isPlaying) {
                val currentPosition = currentPlayer.currentPosition
                val currentString = convertMillisToMinutesAndSecondsString(currentPosition)
                binding.progressDurationTv.text = currentString

                binding.seekBar.value = currentPosition.toFloat()

                sendEmptyMessageDelayed(1, 1000)
            }
        }
    }
}