package com.xty.base.view

import android.Manifest
import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Handler
import android.os.Message
import android.util.AttributeSet
import android.view.MotionEvent
import android.widget.Button
import androidx.core.content.ContextCompat
import com.mylhyl.acp.Acp
import com.mylhyl.acp.AcpListener
import com.mylhyl.acp.AcpOptions
import com.xty.base.R
import com.xty.base.dialog.ChartDialogManager
import com.xty.common.FileUtils
import com.xty.common.LogUtils
import java.io.File

/**
 * 自定义按钮 实现录音等功能
 */
@SuppressLint("AppCompatCustomView")
class AudioRecorderButton(mContext: Context?, attrs: AttributeSet?) : Button(mContext, attrs),
    AudioRecorderManager.AudioStateListener {

    //手指滑动 距离
    private val DISTANCE_Y_CANCEL = 50

    //状态
    private val STATE_NORMAL = 1
    private val STATE_RECORDING = 2
    private val STATE_WANT_TO_CANCEL = 3

    //当前状态
    private var mCurState = STATE_NORMAL

    //已经开始录音
    private var isRecording = false

    private var mDialogManager: ChartDialogManager? = null
    private var mAudioManager: AudioRecorderManager? = null

    private var mTime = 0f

    //是否触发onlongclick
    private var mReady = false


    private val audioFilePath by lazy { FileUtils.getCacheFile(context) + File.separator + "recorder_audios" }

    private val permissions: Array<String> by lazy {
           arrayOf( Manifest.permission.RECORD_AUDIO,
               Manifest.permission.READ_PHONE_STATE,
               Manifest.permission.WRITE_EXTERNAL_STORAGE)
    }

    init {
        mDialogManager = ChartDialogManager(context)
        mAudioManager = AudioRecorderManager.getInstance()

        mAudioManager!!.setOnAudioStateListener(this)
        //按钮长按 准备录音 包括start
        setOnLongClickListener {
            if (checkPermissionAllGranted()) {
                mReady = true
                mAudioManager!!.prepareAudio(audioFilePath)
            } else {
                getAudioPermission(object : AcpListener {
                    override fun onGranted() {
                        LogUtils.d("Audio", "onGranted!!!! ")
                        //这个地方不做处理
//                        reset()
                    }

                    override fun onDenied(permissions: List<String>) {
                        LogUtils.d("Audio", "onDenied!!!!")
                        reset()
                    }
                })
            }
            false
        }
    }

    private fun getAudioPermission(acpListener: AcpListener) {
        Acp.getInstance(context).request(
            AcpOptions.Builder()
                .setPermissions(
                    permissions[0],
                    permissions[1],
                    permissions[2]
                ).build(), acpListener
        )
    }

    /**
     * 检查是否获取所有权限
     */
    private fun checkPermissionAllGranted(): Boolean {
        for (str in permissions){
            // 只要有一个权限没有被授予, 则直接返回 false
            return ContextCompat.checkSelfPermission(context, str)== PackageManager.PERMISSION_GRANTED
        }
        return true
    }

    /**
     * 录音完成后的回调
     */
    interface AudioFinishRecorderListener {
        //时长  和 文件
        fun onFinish(seconds: Float, filePath: String?)
    }

    private var mListener: AudioFinishRecorderListener? = null

    fun setAudioFinishRecorderListener(listener: AudioFinishRecorderListener?) {
        mListener = listener
    }

    //获取音量大小的Runnable
    private val mGetVoiceLevelRunnable = Runnable {
        while (isRecording) {
            try {
                Thread.sleep(100)
                mTime += 0.1.toFloat()
                mHandler.sendEmptyMessage(MSG_VOICE_CHANGED)
            } catch (e: InterruptedException) {
                e.printStackTrace()
            }
        }
    }
    private val mHandler: Handler = object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                MSG_AUDIO_PREPARED -> {
                    if (mReady) {
                        LogUtils.d("Audio", "MSG_AUDIO_PREPARED")
                        mDialogManager!!.showRecordingDialog()
                        isRecording = true
                        changeState(STATE_RECORDING)
                        Thread(mGetVoiceLevelRunnable).start()
                    } else {
                        LogUtils.d("Audio", "MSG_AUDIO_PREPARED is Not Ready!")
                        reset()
                    }
                }
                MSG_VOICE_CHANGED -> mDialogManager!!.updateVoiceLevel(
                    mAudioManager!!.getVoiceLevel(
                        7
                    )
                )
                MSG_DIALOG_DIMISS -> {
                    mDialogManager!!.dimissDialog()
                }
            }
        }
    }

    override fun wellPrepared() {
        mHandler.sendEmptyMessage(MSG_AUDIO_PREPARED)
    }

    override fun onTouchEvent(event: MotionEvent): Boolean {
        val action = event.action
        val x = event.x.toInt()
        val y = event.y.toInt()
        when (action) {
            MotionEvent.ACTION_DOWN -> {
                //TODO
                isRecording = true
                changeState(STATE_RECORDING)
            }
            MotionEvent.ACTION_MOVE -> {
                if (isRecording) {

                    //根据想x,y的坐标，判断是否想要取消
                    if (wantToCancel(x, y)) {
                        changeState(STATE_WANT_TO_CANCEL)
                    } else {
                        changeState(STATE_RECORDING)
                    }
                }
            }
            MotionEvent.ACTION_UP -> {
                //如果longclick 没触发
                if (!mReady) {
                    reset()
                    return super.onTouchEvent(event)
                }
                //触发了onlongclick 没准备好，但是已经prepared 已经start
                //所以消除文件夹
                if (!isRecording || mTime < 0.6f) {
                    mDialogManager!!.tooShort()
                    mAudioManager!!.cancel()
                    mHandler.sendEmptyMessageDelayed(MSG_DIALOG_DIMISS, 1300)
                } else if (mCurState == STATE_RECORDING) { //正常录制结束
                    mDialogManager!!.dimissDialog()
                    mAudioManager!!.release()
                    if (mListener != null) {
                        mListener!!.onFinish(mTime, mAudioManager!!.getCurrentFilePath())
                    }
                } else if (mCurState == STATE_WANT_TO_CANCEL) {
                    mDialogManager!!.dimissDialog()
                    mAudioManager!!.cancel()
                    //cancel
                }
                reset()
            }
        }
        return super.onTouchEvent(event)
    }

    /**
     * 恢复状态 标志位
     */
    private fun reset() {
        isRecording = false
        mReady = false
        changeState(STATE_NORMAL)
        mTime = 0f
    }

    private fun wantToCancel(x: Int, y: Int): Boolean {
        //如果左右滑出 button
        if (x < 0 || x > width) {
            return true
        }

        //如果上下滑出 button  加上我们自定义的距离
        if (y < -DISTANCE_Y_CANCEL || y > height + DISTANCE_Y_CANCEL) {
            return true
        }

        return false
    }

    //改变状态
    private fun changeState(state: Int) {
        LogUtils.d("Audio", "changeState curState:$mCurState;;; changeState:$state")
        if (mCurState != state) {
            mCurState = state
            when (state) {
                STATE_NORMAL -> {
                    setBackgroundResource(R.drawable.shape_talk_stroke)
                    setText(R.string.press_talk)
                }
                STATE_RECORDING -> {
                    setBackgroundResource(R.drawable.shape_talk_stroke)
                    setText(R.string.release_end)
                    if (isRecording) {
                        mDialogManager!!.recording()
                    }
                }
                STATE_WANT_TO_CANCEL -> {
                    setBackgroundResource(R.drawable.shape_talk_stroke)
                    setText(R.string.want_cancel)
                    mDialogManager!!.wantToCancel()
                }
            }
        }
    }

    companion object {
        private const val MSG_AUDIO_PREPARED = 0X110
        private const val MSG_VOICE_CHANGED = 0X111
        private const val MSG_DIALOG_DIMISS = 0X112
    }

}