package com.ydl.media.audio

import android.content.Context
import android.content.IntentFilter
import android.media.AudioManager
import android.os.Handler
import android.os.Looper
import com.tencent.bugly.Bugly.applicationContext
import com.ydl.media.audio.enums.PlayModeEnum
import com.ydl.media.audio.manager.AudioFocusManager
import com.ydl.media.audio.manager.MediaSessionManager
import com.ydl.media.audio.manager.NotifyManager
import com.ydl.media.audio.model.Music
import com.ydl.media.audio.receiver.NoisyAudioStreamReceiver
import com.ydl.media.audio.utils.PlayProgressUtil
import com.ydl.ydlcommon.utils.LogUtil
import com.yidianling.common.tools.ToastUtil
import tv.danmaku.ijk.media.player.IMediaPlayer
import tv.danmaku.ijk.media.player.IjkMediaPlayer
import java.io.IOException
import java.util.*
import kotlin.collections.ArrayList


/**
 * Created by haorui on 2019-10-27 .
 * Des:
 */
class AudioPlayer private constructor() {

    private var context: Context? = null
    private var audioFocusManager: AudioFocusManager? = null
    var mediaPlayer: IMediaPlayer? = null
    private var handler: Handler? = null
    private var noisyReceiver: NoisyAudioStreamReceiver? = null
    private var noisyFilter: IntentFilter? = null
    private var musicList: MutableList<Music> = ArrayList()
    private val listeners = ArrayList<OnPlayerEventListener>()
    private var state = STATE_IDLE

    private val mPublishRunnable = object : Runnable {
        override fun run() {
            if (isPlaying) {
                val current = (mediaPlayer!!.currentPosition * 1.0).toFloat()
                val du = mediaPlayer!!.duration.toFloat()
                var percent = (current * 100 / du).toInt()
                //保存进度
                if (autoSaveProgress) {
                    PlayProgressUtil.saveProgress(
                        context,
                        playMusic!!.path,
                        (if (percent == 99 || percent == 100) 0 else current.toInt())
                    )
                }
                for (listener in listeners) {
                    listener.onPublish(percent, current.toLong())
                }
            }
            handler!!.postDelayed(this, TIME_UPDATE)
        }
    }

    val audioSessionId: Int
        get() = if (mediaPlayer != null)mediaPlayer!!.audioSessionId else 0

    val audioPosition: Long
        get() = if (isPlaying || isPausing) {
            mediaPlayer!!.currentPosition.toLong()
        } else {
            0
        }

    val playMusic: Music?
        get() = if (musicList.isEmpty()) {
            null
        } else musicList[playPosition]

    val isPlaying: Boolean
        get() = state == STATE_PLAYING

    val isPausing: Boolean
        get() = state == STATE_PAUSE

    val isPreparing: Boolean
        get() = state == STATE_PREPARING

    val isIdle: Boolean
        get() = state == STATE_IDLE

    var playPosition: Int = 0
        get() {
            if (field < 0 || field >= musicList.size) {
                field = 0
            }
            return field
        }

    /**
     * 设置播放模式
     * 默认为列表循环
     */
    var playMode = PlayModeEnum.LIST_LOOP
    /**
     * 是否自动保存播放进度
     */
    var autoSaveProgress = false
    /**
     * 是否显示通知栏
     */
    var isShowNotify = false

    private object SingletonHolder {
        val instance = AudioPlayer()
    }

    /**
     * 初始化播放器
     */
    fun init(context: Context) {
        this.context = context.applicationContext
        audioFocusManager = AudioFocusManager(context)
        mediaPlayer = IjkMediaPlayer()
        try {
            (mediaPlayer as IjkMediaPlayer).setOption(
                IjkMediaPlayer.OPT_CATEGORY_FORMAT,
                "dns_cache_clear",
                1
            )
        } catch (e: Exception) {
            LogUtil.e(e.message)
        }

        mediaPlayer!!.setOnPreparedListener { mp ->
            if (isPreparing) {
                if (autoSaveProgress) {
                    //自动播放
                    var time = PlayProgressUtil.getProgress(context, playMusic!!.path)
                    if (time > 0) {
                        startPlayer()
                        seekTo(position = time.toLong())
                    } else {
                        startPlayer()
                    }
                } else {
                    startPlayer()
                }
            }
            for (listener in listeners) {
                listener.onPrepared(mediaPlayer!!.duration)
            }
        }
        mediaPlayer!!.setOnBufferingUpdateListener { mp, percent ->
            for (listener in listeners) {
                listener.onBufferingUpdate(percent)
            }
        }
        mediaPlayer!!.setOnCompletionListener {
            if (autoSaveProgress) {
                PlayProgressUtil.saveProgress(applicationContext, playMusic!!.path, 0)
            }

            for (listener in listeners) {
                listener.onComplete()
            }

            if (playMode == PlayModeEnum.SINGLE) {
                stopPlayer()
                playMode = PlayModeEnum.LIST_LOOP
                return@setOnCompletionListener
            }

            next()
        }
        handler = Handler(Looper.getMainLooper())
        noisyReceiver = NoisyAudioStreamReceiver()
        noisyFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)

    }

    /**
     * 添加播放监听
     */
    fun addOnPlayEventListener(listener: OnPlayerEventListener) {
        if (!listeners.contains(listener)) {
            listeners.add(listener)
        }
    }

    /**
     * 移除播放监听
     */
    fun removeOnPlayEventListener(listener: OnPlayerEventListener) {
        listeners.remove(listener)
    }

    /**
     * 添加播放列表
     */
    fun addPlayList(music: ArrayList<Music>) {
        if (music.isEmpty()) {
            return
        }
        musicList.clear()
        musicList.addAll(music)
        playMode = PlayModeEnum.LIST_LOOP
        autoSaveProgress = false
    }

    /**
     * 单曲模式播放音乐
     */
    fun singlePlay(music: Music, isAutoSaveProgress: Boolean = false) {
        musicList.clear()
        musicList.add(music)
        playMode = PlayModeEnum.SINGLE
        autoSaveProgress = isAutoSaveProgress
        play(0)
    }

    /**
     * 单曲循环模式播放音乐
     */
    fun singleCirclePlay(music: Music) {
        musicList.clear()
        musicList.add(music)
        playMode = PlayModeEnum.SINGLE_LOOP
        autoSaveProgress = false
        play(0)
    }

    /**
     * 添加后自动播放
     */
    fun addAndPlay(music: Music) {
        var position = musicList.indexOf(music)
        if (position < 0) {
            musicList.add(music)
            position = musicList.size - 1
        }
        play(position)
    }

    /**
     * 播放第一首
     */
    fun play() {
        play(0)
    }

    /**
     * 加载指定索引的音乐
     */
    fun play(position: Int) {
        var position = position
        if (musicList.isEmpty()) {
            return
        }

        if (position < 0) {
            position = musicList.size - 1
        } else if (position >= musicList.size) {
            position = 0
        }

        playPosition = position

        val music = playMusic

        try {
            mediaPlayer!!.reset()
            mediaPlayer!!.dataSource = music!!.path
            mediaPlayer!!.prepareAsync()
            state = STATE_PREPARING
            for (listener in listeners) {
                listener.onChange(music)
            }
            if (isShowNotify) {
                NotifyManager.get().showPlay(music)
                MediaSessionManager.get().updateMetaData(music)
                MediaSessionManager.get().updatePlaybackState()
            }
        } catch (e: IOException) {
            e.printStackTrace()
            ToastUtil.toastShort("当前歌曲无法播放")
        }

    }

    /**
     * 从列表里移除播放音乐
     */
    fun delete(position: Int) {
        val music = musicList!!.removeAt(position)
        if (playPosition > position) {
            playPosition -= 1
        } else if (playPosition == position) {
            if (isPlaying || isPreparing) {
                playPosition -= 1
                next()
            } else {
                stopPlayer()
                for (listener in listeners) {
                    listener.onChange(playMusic!!)
                }
            }
        }
    }

    /**
     * 暂停或者播放音乐
     */
    fun playPause() {
        if (isPreparing) {
            stopPlayer()
        } else if (isPlaying) {
            pausePlayer()
        } else if (isPausing) {
            startPlayer()
        } else {
            play(playPosition)
        }
    }

    /**
     *开始播放
     */
    fun startPlayer() {
        if (!isPreparing && !isPausing) {
            return
        }
        if (audioFocusManager!!.requestAudioFocus()) {
            mediaPlayer!!.start()
            state = STATE_PLAYING
            handler!!.post(mPublishRunnable)
            if (isShowNotify) {
                NotifyManager.get().showPlay(playMusic)
                MediaSessionManager.get().updatePlaybackState()
            }
            context!!.registerReceiver(noisyReceiver, noisyFilter)
            for (listener in listeners) {
                listener.onPlayerStart()
            }
        }
    }

    /**
     * 暂停播放器
     */
    @JvmOverloads
    fun pausePlayer(abandonAudioFocus: Boolean = true) {
        if (!isPlaying) {
            return
        }

        mediaPlayer!!.pause()
        state = STATE_PAUSE
        handler!!.removeCallbacks(mPublishRunnable)
        if (isShowNotify) {
            NotifyManager.get().showPause(playMusic)
            MediaSessionManager.get().updatePlaybackState()
        }
        context!!.unregisterReceiver(noisyReceiver)
        if (abandonAudioFocus) {
            audioFocusManager!!.abandonAudioFocus()
        }

        for (listener in listeners) {
            listener.onPlayerPause()
        }
    }

    /**
     * 停止播放器
     */
    fun stopPlayer() {
        if (isIdle) {
            return
        }

        pausePlayer()
        musicList.clear()
        mediaPlayer!!.reset()
        state = STATE_IDLE
    }

    /**
     * 下一首
     */
    operator fun next() {
        if (musicList.isEmpty()) {
            return
        }

        var playPosition = when (playMode) {
            PlayModeEnum.SHUFFLE -> Random().nextInt(musicList.size)
            PlayModeEnum.SINGLE_LOOP -> playPosition
            PlayModeEnum.LIST_LOOP -> playPosition + 1
            else -> playPosition + 1
        }

        play(playPosition);
    }

    /**
     * 上一首
     */
    fun prev() {
        if (musicList.isEmpty()) {
            return
        }
        when (playMode) {
            PlayModeEnum.SHUFFLE -> play(Random().nextInt(musicList.size))
            PlayModeEnum.SINGLE_LOOP -> play(playPosition)
            PlayModeEnum.LIST_LOOP -> play(playPosition - 1)
            else -> play(playPosition - 1)
        }
    }

    /**
     * 跳转到指定的时间位置
     * @param percent 百分比
     * @param position 时间点
     */
    fun seekTo(percent: Int = -1, position: Long = -1) {
        if (isPlaying || isPausing) {

            var currentPosition = 0L
            var currentPercent = 0

            if (position != (-1).toLong()) {
                val current = (currentPosition * 1.0).toFloat()
                val du = mediaPlayer!!.duration.toFloat()
                currentPercent = (current * 100 / du).toInt()

                currentPosition = position
            } else {
                currentPosition = percent * mediaPlayer!!.duration / 100
            }

            mediaPlayer!!.seekTo(currentPosition)
            MediaSessionManager.get().updatePlaybackState()
            if (autoSaveProgress) {
                PlayProgressUtil.saveProgress(
                    context,
                    musicList[playPosition].coverPath,
                    currentPosition.toInt()
                )
            }
            for (listener in listeners) {
                listener.onPublish(currentPercent, currentPosition)
            }
        }
    }

    /**
     * 获取播放列表
     */
    fun getMusicList(): List<Music>? {
        return musicList
    }

    /**
     * 获取音乐时长
     */
    fun getDuration(): Long {
        return mediaPlayer?.duration ?: 0
    }

    companion object {
        private val STATE_IDLE = 0
        private val STATE_PREPARING = 1
        private val STATE_PLAYING = 2
        private val STATE_PAUSE = 3

        private val TIME_UPDATE = 300L

        fun get(): AudioPlayer {
            return SingletonHolder.instance
        }
    }
}
