package com.adealink.weparty.im.session.adapter.viewbinder

import android.os.Build
import android.view.LayoutInflater
import android.view.ViewGroup
import com.adealink.frame.aab.util.getCompatColor
import com.adealink.frame.log.Log
import com.adealink.frame.util.onClick
import com.adealink.frame.util.runOnUiThread
import com.adealink.weparty.commonui.ext.gone
import com.adealink.weparty.commonui.ext.isViewValid
import com.adealink.weparty.commonui.ext.show
import com.adealink.weparty.commonui.util.formatSecondsTo00
import com.adealink.weparty.im.R
import com.adealink.weparty.im.databinding.LayoutSessionMessageBaseBinding
import com.adealink.weparty.im.databinding.LayoutSessionMessageSoundBinding
import com.adealink.weparty.module.im.data.TAG_IM_SESSION_SOUND
import com.adealink.weparty.util.formatTimeTo
import com.adealink.weparty.util.isSupportSpeedPlay
import com.tencent.qcloud.tuicore.interfaces.TUIValueCallback
import com.tencent.qcloud.tuicore.util.ToastUtil
import com.tencent.qcloud.tuikit.timcommon.interfaces.OnItemClickListener
import com.tencent.qcloud.tuikit.timcommon.util.DateTimeUtil
import com.tencent.qcloud.tuikit.timcommon.util.FileUtil
import com.tencent.qcloud.tuikit.tuichat.TUIChatService
import com.tencent.qcloud.tuikit.tuichat.bean.message.SoundMessageBean
import com.tencent.qcloud.tuikit.tuichat.component.audio.AudioPlayer
import com.tencent.qcloud.tuikit.tuichat.presenter.ChatFileDownloadPresenter
import java.util.Timer
import java.util.TimerTask
import kotlin.math.max
import kotlin.math.min

/**
 * 对照: SoundMessageHolder
 */

class SoundMessageViewHolder(
    rootBinding: LayoutSessionMessageBaseBinding,
    binging: LayoutSessionMessageSoundBinding
) : MessageViewHolder<SoundMessageBean, LayoutSessionMessageSoundBinding>(rootBinding, binging) {

    companion object {
        val PLAY_SPEED = arrayOf(1f, 2f, 3f)
    }

    private var mTimer: Timer? = null
    private var times = 0
    private var playSpeedIndex = 0

    private var downloadSoundCallback: TUIValueCallback<*>? = null

    override fun initView(
        binding: LayoutSessionMessageSoundBinding,
        msg: SoundMessageBean,
        onItemClickListener: OnItemClickListener?
    ) {
        val durationStr = formatSecondsTo00(max(msg.getDuration(), 1)) //音频时间最小展示1s
        resetTimerStatus(binding, durationStr)
        binding.root.onClick {
            onSoundClick(binding, msg, msg.getDuration(), durationStr)
        }
        //倍数播放
        showSpeedBtn(binding, msg, isPlaying(msg))
    }

    override fun onBindSelfMessage(
        binding: LayoutSessionMessageSoundBinding,
        msg: SoundMessageBean
    ) {
        setMessageTime(binding, msg)
        //播放进度颜色
        binding.vPlayView.setColor(
            lineColor = getCompatColor(R.color.im_sound_play_self_line_color),
            lineHintColor = getCompatColor(R.color.im_sound_play_self_line_hint_color),
            cursorColor = getCompatColor(R.color.im_sound_play_self_cursor_color)
        )
        setReadStatus(binding, msg, true)
    }

    override fun onBindOtherMessage(
        binding: LayoutSessionMessageSoundBinding,
        msg: SoundMessageBean
    ) {
        setMessageTime(binding, msg)
        //播放进度颜色
        binding.vPlayView.setColor(
            lineColor = getCompatColor(R.color.im_sound_play_other_line_color),
            lineHintColor = getCompatColor(R.color.im_sound_play_other_line_hint_color),
            cursorColor = if (msg.isUnread) {
                getCompatColor(R.color.im_sound_play_other_cursor_color)
            } else {
                getCompatColor(R.color.im_sound_play_other_cursor_read_color)
            }
        )
        setReadStatus(binding, msg, false)
    }

    private fun resetTimerStatus(
        binding: LayoutSessionMessageSoundBinding,
        timeString: String?
    ) {
        mTimer?.cancel()
        mTimer = null
        times = 0
        playSpeedIndex = 0
        binding.btnPlay.setImageResource(R.drawable.im_session_sound_play_ic)
        binding.tvSelfSpeed.text = "1"
        binding.tvOtherSpeed.text = "1"
        binding.vPlayView.stop()
        binding.tvDuration.text = timeString
        binding.btnSelfSpeed.gone()
        binding.btnOtherSpeed.gone()
    }

    private fun isPlaying(message: SoundMessageBean): Boolean {
        val soundPath = ChatFileDownloadPresenter.getSoundPath(message)
        return AudioPlayer.getInstance().isPlaying()
                && AudioPlayer.getInstance().path == soundPath
    }

    private fun onSoundClick(
        binding: LayoutSessionMessageSoundBinding,
        message: SoundMessageBean,
        soundSecond: Int,
        soundDurationStr: String?
    ) {
        val soundPath = ChatFileDownloadPresenter.getSoundPath(message)
        if (AudioPlayer.getInstance().isPlaying()) {
            AudioPlayer.getInstance().stopPlay()
            resetTimerStatus(binding, soundDurationStr)
            if (AudioPlayer.getInstance().path == soundPath) {
                //播放同一个音频
                return
            }
        }
        if (!FileUtil.isFileExists(soundPath)) {
            ToastUtil.toastShortMessage(
                TUIChatService.getAppContext()
                    .getString(R.string.im_sound_play_tip_for_voice_not_download)
            )
            getSound(message)
            return
        }

        if (soundSecond > 1) {
            //音频时间大于1s才启动定时器
            if (mTimer == null) {
                mTimer = Timer()
            }
            mTimer?.schedule(object : TimerTask() {
                override fun run() {
                    runOnUiThread {
                        if (times < soundSecond) {
                            times = min(times + PLAY_SPEED[playSpeedIndex].toInt(), soundSecond)
                            val s = DateTimeUtil.formatSecondsTo00(times)
                            binding.tvDuration.text = s
                        } else {
                            binding.tvDuration.text = soundDurationStr
                        }
                    }
                }
            }, 0, 1000)
        }

        binding.btnPlay.setImageResource(R.drawable.im_session_sound_stop_ic)
        message.setPlayed()
        AudioPlayer.getInstance().startPlay(soundPath, object : AudioPlayer.Callback {
            override fun onPlayStart() {
                if (isViewValid()) {
                    startPlayAnimation(
                        binding,
                        soundSecond * 1000L,
                        0,
                        PLAY_SPEED[playSpeedIndex]
                    )
                    showSpeedBtn(binding, message, true)
                }
            }

            override fun onCompletion(success: Boolean?) {
                Log.d(
                    TAG_IM_SESSION_SOUND,
                    "onSoundClick, onCompletion, message:$message"
                )
                if (isViewValid()) {
                    resetTimerStatus(binding, soundDurationStr)
                }
            }
        })
    }

    private fun showSpeedBtn(
        binding: LayoutSessionMessageSoundBinding,
        message: SoundMessageBean,
        isPlaying: Boolean,
    ) {
        if (message.isSelf) {
            binding.btnOtherSpeed.gone()
            if (isSupportSpeedPlay() && isPlaying) {
                binding.btnSelfSpeed.show()
                binding.btnSelfSpeed.onClick {
                    changeClaySpeed(binding, message)
                }
            } else {
                binding.btnSelfSpeed.gone()
            }
        } else {
            binding.btnSelfSpeed.gone()
            if (isSupportSpeedPlay() && isPlaying) {
                binding.btnOtherSpeed.show()
                binding.btnOtherSpeed.onClick {
                    changeClaySpeed(binding, message)
                }
            } else {
                binding.btnOtherSpeed.gone()
            }
        }
    }

    private fun startPlayAnimation(
        binding: LayoutSessionMessageSoundBinding,
        allDuration: Long, //所有时长(毫秒)
        duration: Long, //剩余时长(毫秒)
        speed: Float, //倍速
    ) {
        val soundPlayView = binding.vPlayView
        soundPlayView.start(allDuration, duration, speed)
    }


    private fun getSound(messageBean: SoundMessageBean?) {
        downloadSoundCallback = object : TUIValueCallback<Any?>() {
            override fun onProgress(currentSize: Long, totalSize: Long) {
                Log.d(
                    TAG_IM_SESSION_SOUND,
                    "downloadSound progress current: $currentSize, total:$totalSize"
                )
            }

            override fun onError(code: Int, desc: String?) {
                Log.e(TAG_IM_SESSION_SOUND, "getSoundToFile failed code = $code, info = $desc")
                //ToastUtil.toastLongMessage("getSoundToFile failed code = " + code + ", info = " + desc)
            }

            override fun onSuccess(obj: Any?) {
                Log.d(TAG_IM_SESSION_SOUND, "get sound success")
            }
        }
        ChatFileDownloadPresenter.downloadSound(messageBean, downloadSoundCallback)
    }

    private fun changeClaySpeed(
        binding: LayoutSessionMessageSoundBinding,
        message: SoundMessageBean
    ) {
        if (!isPlaying(message)) {
            return
        }
        playSpeedIndex = (playSpeedIndex + 1) % PLAY_SPEED.size
        val nextSpeed = PLAY_SPEED[playSpeedIndex]
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            AudioPlayer.getInstance().setSpeed(nextSpeed)
            if (message.isSelf) {
                binding.tvSelfSpeed.text = nextSpeed.toInt().toString()
            } else {
                binding.tvOtherSpeed.text = nextSpeed.toInt().toString()
            }
            Log.d(TAG_IM_SESSION_SOUND, "changeClaySpeed, speed: $nextSpeed")
            Log.d(
                TAG_IM_SESSION_SOUND,
                "                      : allTime: ${message.duration * 1000}, currentTim:${AudioPlayer.getInstance().playPosition}"
            )

            startPlayAnimation(
                binding,
                message.duration * 1000L,
                AudioPlayer.getInstance().playPosition.toLong(),
                nextSpeed
            )
        }
    }

    private fun setMessageTime(
        binding: LayoutSessionMessageSoundBinding,
        item: SoundMessageBean
    ) {
        binding.tvTime.text = formatTimeTo((item.messageTime * 1000), "HH:mm")
    }

    private fun setReadStatus(
        binding: LayoutSessionMessageSoundBinding,
        msg: SoundMessageBean,
        isSelf: Boolean
    ) {
        if (!isSelf) {
            binding.ivReadStatus.gone()
            return
        }
        binding.ivReadStatus.show()
        if (msg.isPeerRead) {
            binding.ivReadStatus.setImageResource(R.drawable.im_session_message_read_ic)
        } else {
            binding.ivReadStatus.setImageResource(R.drawable.im_session_message_unread_ic)
        }
    }

}

class SoundMessageViewBinder(
    onItemClickListener: OnItemClickListener
) : BaseMessageViewBinder<SoundMessageBean, LayoutSessionMessageSoundBinding, SoundMessageViewHolder>(
    onItemClickListener
) {

    override fun onCreateMessageHolder(
        rootBinder: LayoutSessionMessageBaseBinding,
        inflater: LayoutInflater,
        parent: ViewGroup
    ): SoundMessageViewHolder {
        return SoundMessageViewHolder(
            rootBinder,
            LayoutSessionMessageSoundBinding.inflate(
                inflater,
                parent,
                true
            )
        )
    }

}