package com.yidianling.muse.helper

import android.content.Context
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.MediaPlayer
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import java.util.concurrent.TimeUnit
import kotlin.properties.Delegates

class MediaPlayerManager private constructor() {

    private var listener:OnMediaPlayerManagerListener?=null

    private var mCurrentListIndex = 0
    private var mAudioPaths = mutableListOf<String>()

    private var mMediaId:Long? = null
    private var mTime = 0L
    private var mTimeOffStatus = false

    private var mDisposable:Disposable? = null
    private var mObservable: Observable<Long>? = null
    private var mObserver: Observer<Long>? = null

    fun setMediaId(mediaId:Long?){
        mMediaId = mediaId
    }

    fun getMediaId():Long? = mMediaId

    fun getTimeOff():Long = mTime

    fun getTimeOffStatus():Boolean = mTimeOffStatus

    fun setTimeOffStatus(timeOffStatus:Boolean){
        mTimeOffStatus = timeOffStatus
    }

    fun setTimeOff(time:Long){
        mTime = time
    }

    fun setAudioPath(path: String,isLoop:Boolean = false){

        val attrs = AudioAttributes.Builder()
            .setContentType(AudioAttributes.CONTENT_TYPE_MUSIC)
            .setUsage(AudioAttributes.USAGE_MEDIA)
            .setLegacyStreamType(AudioManager.STREAM_MUSIC)
            .build()

        mPath = path
        mMediaPlayer?.reset()
        mMediaPlayer?.setAudioAttributes(attrs)
        mMediaPlayer?.setDataSource(path)
        mMediaPlayer?.prepareAsync()
        mMediaPlayer?.setOnPreparedListener {
            listener?.onPrepared(it)
            if (isLoop){
                mMediaPlayer?.seekTo(0)
            }
        }
    }

    fun getMediaPlayer():MediaPlayer?  = mMediaPlayer

    fun getAudioPath():String? = mPath

    fun isPlaying() = mMediaPlayer?.isPlaying

    fun play() {
        if (mMediaPlayer?.isPlaying == true) return
        mMediaPlayer?.start()
    }

    fun pause() {
        if (mMediaPlayer?.isPlaying == true) mMediaPlayer?.pause()
    }

    fun seekTo(position: Int) {
        mMediaPlayer?.seekTo(position)
    }

    fun stop() {
        mMediaPlayer?.stop()
    }

    fun release() {
        mMediaPlayer?.stop()
    }

    fun setOnPreparedListener(listener: OnMediaPlayerManagerListener){
        this.listener = listener
    }

    fun initRxTimeOff(time: Long) {
        if (time ==null && time <=0){
            mDisposable?.dispose()
        }

        mObservable = Observable.interval(0, 1, TimeUnit.SECONDS)
            .take(time / 1000 + 1)
            .map { t -> time - t * 1000 }
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())

        mObserver = object : Observer<Long> {
            override fun onSubscribe(d: Disposable) {
                mDisposable = d
            }

            override fun onNext(t: Long) {
                mTime = t
            }

            override fun onError(e: Throwable) {

            }

            override fun onComplete() {

            }
        }

        if (mObserver != null && mObserver is Observer<Long>) {
            mObservable?.subscribe(mObserver as Observer<Long>)
        }

        if (mDisposable?.isDisposed == true && mObserver != null && mObserver is Observer<Long>) {
            mObservable?.subscribe(mObserver as Observer<Long>)
        }

    }

    fun dispose() {
        mTime = 0
        mDisposable?.dispose()
    }

    companion object {

        private var mContext: Context by Delegates.notNull()

        private var mMediaPlayer:MediaPlayer? = null

        private var mPath:String? = null

        @Volatile
        private var instance: MediaPlayerManager? = null

        fun getInstance(context: Context): MediaPlayerManager? {
            return when{
                instance != null -> instance
                else -> synchronized(this) {
                    if (instance == null){
                        mContext = context
                        mMediaPlayer = MediaPlayer()
                        instance = MediaPlayerManager()
                    }
                    instance
                }
            }
        }
    }


    interface OnMediaPlayerManagerListener{
        fun onPrepared(mediaPlayer: MediaPlayer)
    }

}