package com.ydl.media.music

import android.content.Context
import android.content.IntentFilter
import android.media.AudioManager
import android.media.MediaPlayer
import android.os.Handler
import android.os.Looper
import com.ydl.media.music.enums.PlayModeEnum
import com.ydl.media.music.manager.AudioFocusManager
import com.ydl.media.music.manager.MediaSessionManager
import com.ydl.media.music.manager.NotifyManager
import com.ydl.media.music.model.Music
import com.ydl.media.music.receiver.NoisyAudioStreamReceiver
import com.yidianling.common.tools.ToastUtil
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: MediaPlayer? = 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) {
                for (listener in listeners) {
                    listener.onPublish(mediaPlayer!!.currentPosition)
                }
            }
            handler!!.postDelayed(this, TIME_UPDATE)
        }
    }

    val audioSessionId: Int
        get() = mediaPlayer!!.audioSessionId

    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

    private object SingletonHolder {
        val instance = AudioPlayer()
    }

    /**
     * 初始化播放器
     */
    fun init(context: Context) {
        this.context = context.applicationContext
        audioFocusManager = AudioFocusManager(context)
        mediaPlayer = MediaPlayer()
        handler = Handler(Looper.getMainLooper())
        noisyReceiver = NoisyAudioStreamReceiver()
        noisyFilter = IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)
        mediaPlayer!!.setOnCompletionListener {
            if (playMode == PlayModeEnum.SINGLE) {
                stopPlayer()
                playMode = PlayModeEnum.LIST_LOOP
                return@setOnCompletionListener
            }
            next()
        }
        mediaPlayer!!.setOnPreparedListener { mp ->
            if (isPreparing) {
                startPlayer()
            }
        }
        mediaPlayer!!.setOnBufferingUpdateListener { mp, percent ->
            for (listener in listeners) {
                listener.onBufferingUpdate(percent)
            }
        }
    }

    /**
     * 添加播放监听
     */
    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)
    }

    /**
     * 单曲模式播放音乐
     */
    fun singlePlay(music: Music) {
        musicList.clear()
        musicList.add(music)
        playMode = PlayModeEnum.SINGLE
        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!!.setDataSource(music!!.path)
            mediaPlayer!!.prepareAsync()
            state = STATE_PREPARING
            for (listener in listeners) {
                listener.onChange(music)
            }
            if (playMode != PlayModeEnum.SINGLE){
                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 (playMode != PlayModeEnum.SINGLE){
                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)
        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()
        mediaPlayer!!.reset()
        state = STATE_IDLE
    }

    /**
     * 下一首
     */
    operator fun next() {
        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)
        }
    }

    /**
     * 上一首
     */
    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 msec 时间
     */
    fun seekTo(msec: Int) {
        if (isPlaying || isPausing) {
            mediaPlayer!!.seekTo(msec)
            MediaSessionManager.get().updatePlaybackState()
            for (listener in listeners) {
                listener.onPublish(msec)
            }
        }
    }

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

    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
        }
    }
}
