package com.yidianling.muse.service

import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.Intent.FLAG_ACTIVITY_NEW_TASK
import android.graphics.PixelFormat
import android.media.MediaPlayer
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.util.DisplayMetrics
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
import android.view.WindowManager
import android.widget.ImageView
import android.widget.TextView
import androidx.core.app.NotificationCompat
import com.bumptech.glide.Glide
import com.ydl.ydlcommon.data.http.ThrowableConsumer
import com.ydl.ydlcommon.utils.actionutil.ActionCountUtils
import com.yidianling.home.http.MuseHttp
import com.yidianling.muse.R
import com.yidianling.muse.activity.PlayMeditationActivity
import com.yidianling.muse.bean.MeditationPlayModuleBean
import com.yidianling.muse.constants.MuseBIConstants
import com.yidianling.muse.event.MeditationFloatEvent
import com.yidianling.muse.helper.FloatViewTouchListener
import com.yidianling.muse.helper.MediaPlayerManager
import com.yidianling.muse.utils.MediaPlayerTimeUtil
import de.greenrobot.event.EventBus
import io.feeeei.circleseekbar.CircleSeekBar
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 kotlinx.android.synthetic.main.activity_play_meditation.*
import kotlinx.android.synthetic.main.player_control_view.*
import java.util.*
import java.util.concurrent.TimeUnit
import kotlin.math.roundToInt

class MeditationWindowService : Service() {

    private lateinit var mWindowManager: WindowManager
    private var floatRootView: View? = null

    private var ivClose: ImageView? = null
    private var ivCover: ImageView? = null
    private var tvTitle: TextView? = null
    private var ivProgress: CircleSeekBar? = null
    private var ivPlayOrPause: ImageView? = null

    private var mMediaPlayer: MediaPlayer? = null

    private var mTimer = Timer()

    private var mCurrentMeditation: MeditationPlayModuleBean.MeditationDetail? = null

    private var mMeditations = mutableListOf<MeditationPlayModuleBean.MeditationDetail>()

    private var windowIsShow = false

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

    private var currentMediaId:Long? = null

    inner class MeditationBinder : Binder() {
        val service: MeditationWindowService
            get() = this@MeditationWindowService
    }

    override fun onCreate() {
        super.onCreate()
        EventBus.getDefault().register(this)

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
            val channel = NotificationChannel("壹点灵", "play", NotificationManager.IMPORTANCE_HIGH)
            manager.createNotificationChannel(channel)
            val notification = NotificationCompat.Builder(this, "壹点灵").build()
            startForeground(1, notification)
        }
    }

    private fun showWindow() {
        mWindowManager = getSystemService(WINDOW_SERVICE) as WindowManager
        val outMetrics = DisplayMetrics()
        mWindowManager.defaultDisplay.getMetrics(outMetrics)
        var layoutParams = WindowManager.LayoutParams().apply {
            type = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            } else {
                WindowManager.LayoutParams.TYPE_PHONE
            }
            flags =
                WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL or WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
            format = PixelFormat.RGBA_8888
            width = outMetrics.widthPixels - dp2px(32F)
            height = WRAP_CONTENT
            gravity = Gravity.LEFT or Gravity.TOP

            x = outMetrics.widthPixels /2 - width / 2
            y = outMetrics.heightPixels - dp2px(140F)
        }
        floatRootView =
            LayoutInflater.from(this).inflate(R.layout.layout_meditation_play_float_view, null)
        ivClose = floatRootView?.findViewById(R.id.iv_close)
        ivCover = floatRootView?.findViewById(R.id.iv_cover)
        tvTitle = floatRootView?.findViewById(R.id.tv_title)
        ivProgress = floatRootView?.findViewById(R.id.progress_bar)
        ivPlayOrPause = floatRootView?.findViewById(R.id.iv_play_status)
        floatRootView?.setOnTouchListener(FloatViewTouchListener(layoutParams, mWindowManager))
        mWindowManager.addView(floatRootView, layoutParams)
        windowIsShow = true
    }

    fun onEventMainThread(event: Any) {
        if (event is com.ydl.ydlcommon.event.MeditationFloatEvent){
            if (event.show!=null && !event.show) {
                    if (event.stop == true){
                        try {
                            mMediaPlayer?.stop()
                        }catch (e:Exception){

                        }
                        hideFloatWindow()
                    }
                    hideFloatWindow()
                }
        }

        if (event is MeditationFloatEvent){
            if (event.time!=null){
                if (event.time>0){
                    initRxTimeOff(event.time)
                }else{
                    mDisposable?.dispose()
                }
            }else{
                if (event.show!=null && !event.show) {
                    if (event.stop == true){
                        try {
                            mMediaPlayer?.stop()
                        }catch (e:Exception){

                        }
                        hideFloatWindow()
                    }
                    hideFloatWindow()
                }
                if (event.show!=null && event.show && event.meditation != null) {
                    if (!windowIsShow) {
                        showWindow()
                    }
                    updateFloatView(event.meditation)
                }
            }
        }


    }

    private fun updateFloatView(meditation: MeditationPlayModuleBean.MeditationDetail) {

        currentMediaId = meditation.mediaId
        MediaPlayerManager.getInstance(this)?.setMediaId(currentMediaId)

        mMediaPlayer = MediaPlayerManager.getInstance(this)?.getMediaPlayer()
        tvTitle?.setOnClickListener {
            //悬浮窗暂停点击事件
            ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")

            val intent = Intent(this, PlayMeditationActivity::class.java)
            intent.putExtra("MEDIA_ID", meditation.mediaId)
            intent.putExtra("MEDITATION_ID", meditation.meditationId)
            intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
            intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
            intent.putExtra("MEDIA_URL", meditation.mediaUrl)

            intent.flags = FLAG_ACTIVITY_NEW_TASK
            startActivity(intent)
        }
        ivCover?.setOnClickListener {
            //悬浮窗暂停点击事件
            ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLICK,"")

            val intent = Intent(this, PlayMeditationActivity::class.java)
            intent.putExtra("MEDIA_ID", meditation.mediaId)
            intent.putExtra("MEDITATION_ID", meditation.meditationId)
            intent.putExtra("MEDITATION_TYPE", meditation.meditationType)
            intent.putExtra("MEDIA_COVER_URL", meditation.coverImageUrl)
            intent.putExtra("MEDIA_URL", meditation.mediaUrl)

            intent.flags = FLAG_ACTIVITY_NEW_TASK
            startActivity(intent)
        }

        if (mMediaPlayer?.isPlaying == true) {
            ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
        } else {
            ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
        }

        ivProgress?.maxProcess = mMediaPlayer?.duration ?: 0
        ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0

        Glide.with(floatRootView!!)
            .load(meditation.coverImageUrl)
            .into(ivCover!!)

        tvTitle?.text = meditation.title

        ivPlayOrPause?.setOnClickListener {
            if (mMediaPlayer?.isPlaying == true) {
                //悬浮窗暂停点击事件
                ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PAUSE_CLICK,"")

                MediaPlayerManager.getInstance(this)?.pause()
                if (meditation.meditationId != null && meditation.mediaId != null) {
                    MuseHttp.getInstance().postMeditationPlayRecord(
                        meditationId = meditation.meditationId!!.toInt(),
                        isQuit = 1, mediaId = meditation.mediaId!!,
                        playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0,
                        isComplete = 0
                    )
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe({

                        }, {
                            object : ThrowableConsumer() {
                                override fun accept(msg: String) {

                                }
                            }
                        })
                }
            } else {
                //悬浮窗播放点击事件
                ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_PLAY_CLICK,"")
                MediaPlayerManager.getInstance(this)?.play()
            }
            if (mMediaPlayer?.isPlaying == true) {
                ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
            } else {
                ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
            }
        }

        mTimer.schedule(object : TimerTask() {
            override fun run() {
                ivProgress?.curProcess = mMediaPlayer?.currentPosition ?: 0
            }
        }, 0, 50)

        mMediaPlayer?.setOnCompletionListener {

            val duration = meditation?.duration?.toInt()?:0
            val currentDuration = (mMediaPlayer?.currentPosition?:0)/1000
            if(meditation.mediaId!=null && meditation.meditationId!=null){
                val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
                if(duration == currentDuration){
                    MediaPlayerTimeUtil.uploadPlayRecord(
                        meditationId = meditation.meditationId.toInt(),
                        mediaId = meditation.mediaId,
                        isQuit = 0,
                        playTime = playTime,
                        isComplete = 1
                    )
                }
            }
            if (mMediaPlayer?.isPlaying == true) {
                ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_play)
            } else {
                ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
            }
        }

        ivClose?.setOnClickListener {
            //悬浮窗关闭点击事件
            ActionCountUtils.count(MuseBIConstants.YDL_MUSE_MEDITATION_WINDOW_CLOSE_CLICK,"")

            if(meditation.mediaId!=null && meditation.meditationId!=null){
                val playTime = (ivProgress?.curProcess?.div(1000.00))?.roundToInt() ?: 0
                MediaPlayerTimeUtil.uploadPlayRecord(
                    meditationId = meditation.meditationId.toInt(),
                    mediaId = meditation.mediaId,
                    isQuit = 0,
                    playTime = playTime,
                    isComplete = 0
                )
            }

            MediaPlayerManager.getInstance(this)?.stop()
            hideFloatWindow()
        }

    }

    private fun hideFloatWindow() {
        if (floatRootView != null && floatRootView?.windowToken != null) {
            if (mWindowManager != null) {
                windowIsShow = false
                mWindowManager.removeViewImmediate(floatRootView)
            }
        }
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        return super.onStartCommand(intent, flags, startId)
    }

    override fun startForegroundService(service: Intent?): ComponentName? {
        return super.startForegroundService(service)
    }

    override fun onDestroy() {
        super.onDestroy()
        if (EventBus.getDefault().isRegistered(this)) {
            EventBus.getDefault().unregister(this)
        }
        mDisposable?.dispose()
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ECLAIR) {
            stopForeground(true)
        }
    }

    override fun onBind(intent: Intent?): IBinder? {
        return MeditationBinder()
    }

    private fun dp2px(dp: Float): Int {
        val scale = resources.displayMetrics.density
        return (dp * scale + 0.5f).toInt()
    }

    private fun initRxTimeOff(time: Long) {
        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) {

            }

            override fun onError(e: Throwable) {

            }

            override fun onComplete() {
                if (mMediaPlayer?.isPlaying == true) {
                    mMediaPlayer?.stop()
                    ivPlayOrPause?.setImageResource(R.drawable.icon_meditation_float_pause)
                }
                hideFloatWindow()
            }
        }

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

    }

}