package com.gingersoft.gsa.other_order_mode.service

import android.annotation.SuppressLint
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.graphics.BitmapFactory
import android.media.AudioAttributes
import android.media.AudioManager
import android.media.SoundPool
import android.os.Binder
import android.os.Build
import android.os.IBinder
import android.os.PowerManager
import android.util.Log
import android.widget.RemoteViews
import androidx.annotation.RequiresApi
import androidx.core.app.NotificationCompat
import com.gingersoft.gsa.cloud.base.application.GsaCloudApplication
import com.gingersoft.gsa.cloud.base.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.constans.AppConstans
import com.gingersoft.gsa.cloud.constans.HttpsConstans
import com.gingersoft.gsa.other_order_mode.R
import com.gingersoft.gsa.other_order_mode.data.network.ServiceCreator
import com.gingersoft.gsa.other_order_mode.ui.activity.OtherOrderActivity
import com.gingersoft.gsa.other_order_mode.util.RxTimerUtil
import com.google.gson.Gson
import io.reactivex.schedulers.Schedulers
import okhttp3.*
import okio.ByteString
import org.json.JSONObject
import java.util.*
import java.util.concurrent.TimeUnit

class GetInfoUpdateService : Service() {

    private val TAG = "eee"
    /**
     * 心跳检测时间
     */
    private val HEART_BEAT_RATE = (58 * 1000).toLong()//每隔15秒进行一次对长连接的心跳检测
    private val WEBSOCKET_HOST_AND_PORT = "${ServiceCreator.ROOT_URL}/ricepon-websocket/js/webSocketServer"//可替换为自己的主机名和端口号

    private var mWebSocket: WebSocket? = null
    var client: OkHttpClient? = null

    var postCallBack: PostCallBack? = null
    private lateinit var mReceiver: ClearHeartBroadcastReceiver

    private var newWakeLock: PowerManager.WakeLock? = null

    val restaurantId by lazy {
        GsaCloudApplication.getRestaurantId(this)
//        26
    }

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


    override fun onCreate() {
        super.onCreate()
        val mFilter = IntentFilter(AppConstans.CLEAR_ORDER_RECEIVING_HEART)
        mReceiver = ClearHeartBroadcastReceiver()
        registerReceiver(mReceiver, mFilter)

        InitSocketThread().start()
        isDestroy = false

        //讓設備在休眠狀態下保持運行
        val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
        newWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, this.javaClass.name)
        //Value                    CPU             Screen           KeyBoard
        //PARTIAL_WAKE_LOCK        On               Off             Off
        //SCREEN_DIM_WAKE_LOCK     On               Dim             Off
        //SCREEN_BRIGHT_WAKE_LOCK  On               Bright          Off
        //FULL_WAKE_LOCK           On               Bright          Bright
        newWakeLock?.acquire()
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.d(TAG, "onStartCommand()")
        // 在API11之后构建Notification的方式
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            createNotificationChannel()
        } else {
            startNotification()
        }
        return super.onStartCommand(intent, flags, startId)
    }

    val CHANNEL_ID = "cloud_gsa"
    /**
     * 创建通知渠道
     */
    @RequiresApi(Build.VERSION_CODES.O)
    fun createNotificationChannel() {
        //设定的通知渠道名称
        val channelName = "New Order Notification"
        //设置通知的重要程度
        val importance = NotificationManager.IMPORTANCE_LOW
        //构建通知渠道
        val channel = NotificationChannel(CHANNEL_ID, channelName, importance)
        channel.description = "New Order Notification"
        //向系统注册通知渠道，注册后不能改变重要性以及其他通知行为
        val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        notificationManager.createNotificationChannel(channel)
        startNotification()
    }

    @SuppressLint("InflateParams")
    private fun startNotification() {
        val broadcastReceiver = Intent(AppConstans.CLEAR_ORDER_RECEIVING_HEART)
        val broadcastIntent = PendingIntent.getBroadcast(this, 10, broadcastReceiver, 0)
//        LocalBroadcastManager.getInstance(context).sendBroadcast(intent);
        val remoteViews = RemoteViews(packageName, R.layout.layout_order_receiving)
        remoteViews.setOnClickPendingIntent(R.id.btn_stop_service, broadcastIntent)
        val intent = Intent(this, OtherOrderActivity::class.java)
        val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)

        //在创建的通知渠道上发送通知
        val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        builder.setSmallIcon(R.mipmap.ic_launcher) //设置通知图标
                .setContentTitle("Ricepon Pos")//设置通知标题
                .setContentText("外賣接單服務")//设置通知内容Takeaway order service
                .setContentIntent(pendingIntent)
                .setContent(remoteViews)
                .setAutoCancel(false) //用户触摸时，自动关闭
                .setOngoing(true)//设置处于运行状态
                .setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
        //将服务置于启动状态 NOTIFICATION_ID指的是创建的通知的ID
        startForeground(123, builder.build())
    }

    inner class MyBind : Binder() {
        fun setOnPostCallBack(postCallBack: PostCallBack?) {
            this@GetInfoUpdateService.postCallBack = postCallBack
        }
    }

    internal inner class InitSocketThread : Thread() {
        override fun run() {
            super.run()
            initSocket()
        }
    }

    // 初始化socket
    private fun initSocket() {
        RxTimerUtil.cancel()
        RxTimerUtil.timer({
            client = OkHttpClient.Builder().readTimeout(0, TimeUnit.MILLISECONDS).build()
            client?.let {
                val request = Request.Builder()
                        .url(WEBSOCKET_HOST_AND_PORT)
                        .build()
                it.newWebSocket(request, object : WebSocketListener() {
                    override fun onOpen(webSocket: WebSocket, response: Response) {//开启长连接成功的回调
                        super.onOpen(webSocket, response)
                        if (!this@GetInfoUpdateService.isDestroy) {
                            mWebSocket = webSocket
                            val token = "weixin_" + restaurantId + "_" + getRandomString(24)
                            Log.e(TAG, "token：$token")
                            webSocket.send(Gson().toJson(MsgBean(1, token)))
                        }
                    }

                    override fun onMessage(webSocket: WebSocket?, text: String?) {//接收消息的回调
                        super.onMessage(webSocket, text)
                        val json = JSONObject(text)
                        val type = json.optInt("type")
                        if (postCallBack != null) {
                            postCallBack!!.callBack(type)
                        }
                        //-1斷開連接,\n-2:消息傳輸錯誤,\n0:連接消息,\n1：登錄通知,\n2：登出通知,\n3：外賣送單通知,\n4：自取送單通知,\n5:歷史訂單通知,\n6:修改訂單狀態通知,\n7:支付成功通知"

                        if (type == 3 || type == 4 || type == 5
                                || type == 6 || type == 7) {
                            if (type == 6) {

                            } else {
                                //播放提示音
                                initSoundPool()
                            }
                        }
                        //收到服务器端传过来的消息text
                        Log.e(TAG, "onMessage：" + text!!)
                    }

                    override fun onMessage(webSocket: WebSocket?, bytes: ByteString?) {
                        super.onMessage(webSocket, bytes)
                        val json = JSONObject(bytes.toString())
                        if (postCallBack != null) {
                            postCallBack!!.callBack(json.optInt("type"))
                        }
                        Log.e(TAG, "onMessage222：" + bytes!!)
                    }

                    override fun onClosing(webSocket: WebSocket?, code: Int, reason: String?) {
                        super.onClosing(webSocket, code, reason)
                        //連接斷開，
                        Log.e(TAG, "onClosing")
//                InitSocketThread().start()//创建一个新的连接

                    }

                    override fun onClosed(webSocket: WebSocket?, code: Int, reason: String?) {
                        super.onClosed(webSocket, code, reason)
                        Log.e(TAG, "onClosed")
                        webSocket?.cancel()
                    }

                    override fun onFailure(webSocket: WebSocket?, t: Throwable?, response: Response?) {//长连接连接失败的回调
                        super.onFailure(webSocket, t, response)
                        Log.e(TAG, "onFailure" + t!!.message)
                        if (!this@GetInfoUpdateService.isDestroy) {
//                        Log.e(TAG, "沒銷毀")
//                        initSocket()//创建一个新的连接
                        } else {
                            webSocket?.cancel()
                            it.dispatcher().cancelAll()
                        }
                    }
                })
                it.dispatcher().executorService().shutdown()
            }
        }, HEART_BEAT_RATE)
    }

    private var soundPool: SoundPool? = null

    fun initSoundPool() {
        //实例化SoundPool
        //sdk版本21是SoundPool 的一个分水岭
        if (soundPool == null) {
            if (Build.VERSION.SDK_INT >= 21) {
                val builder = SoundPool.Builder()
                //传入最多播放音频数量,
                builder.setMaxStreams(1)
                //AudioAttributes是一个封装音频各种属性的方法
                val attrBuilder = AudioAttributes.Builder()
                //设置音频流的合适的属性
                attrBuilder.setLegacyStreamType(AudioManager.STREAM_MUSIC)
                //加载一个AudioAttributes
                builder.setAudioAttributes(attrBuilder.build())
                soundPool = builder.build()
            } else {
                /**
                 * 第一个参数：int maxStreams：SoundPool对象的最大并发流数
                 * 第二个参数：int streamType：AudioManager中描述的音频流类型
                 *第三个参数：int srcQuality：采样率转换器的质量。 目前没有效果。 使用0作为默认值。
                 */
                soundPool = SoundPool(1, AudioManager.STREAM_MUSIC, 0)
            }
        }
        //可以通过四种途径来记载一个音频资源：
        //1.通过一个AssetFileDescriptor对象
        //int load(AssetFileDescriptor afd, int priority)
        //2.通过一个资源ID
        //int load(Context context, int resId, int priority)
        //3.通过指定的路径加载
        //int load(String path, int priority)
        //4.通过FileDescriptor加载
        //int load(FileDescriptor fd, long offset, long length, int priority)
        //声音ID 加载音频资源,这里用的是第二种，第三个参数为priority，声音的优先级*API中指出，priority参数目前没有效果，建议设置为1。
        val voiceId = soundPool!!.load(this, R.raw.newordervocal, 1)
        //异步需要等待加载完成，音频才能播放成功
        soundPool!!.setOnLoadCompleteListener { soundPool, sampleId, status ->
            if (status == 0) {
                //第一个参数soundID
                //第二个参数leftVolume为左侧音量值（范围= 0.0到1.0）
                //第三个参数rightVolume为右的音量值（范围= 0.0到1.0）
                //第四个参数priority 为流的优先级，值越大优先级高，影响当同时播放数量超出了最大支持数时SoundPool对该流的处理
                //第五个参数loop 为音频重复播放次数，0为值播放一次，-1为无限循环，其他值为播放loop+1次
                //第六个参数 rate为播放的速率，范围0.5-2.0(0.5为一半速率，1.0为正常速率，2.0为两倍速率)
                soundPool.play(voiceId, 1f, 1f, 1, 0, 1f)
            }
        }
    }

    /*获取一条随机字符串*/
    fun getRandomString(length: Int): String { //length表示生成字符串的长度
        val base = "abcdefghijklmnopqrstuvwxyz0123456789" + System.currentTimeMillis()
        val random = Random()
        val sb = StringBuffer()
        for (i in 0 until length) {
            val number = random.nextInt(base.length)
            sb.append(base[number])
        }
        return sb.toString()
    }


//    private var sendTime = 0L
    // 发送心跳包

    //    private val mHandler = Handler()
//    private val heartBeatRunnable = object : Runnable {
//        override fun run() {
//            if (!isDestroy) {
//                if (System.currentTimeMillis() - sendTime >= HEART_BEAT_RATE) {
//                    val isSuccess = mWebSocket?.send("0")//发送一个空消息给服务器，通过发送消息的成功失败来判断长连接的连接状态
//                    Log.e(TAG, "連接狀態：$isSuccess")
////                    if (isSuccess != null && !isSuccess) {//长连接已断开
//                    mHandler.removeCallbacks(this)
//                    mWebSocket?.cancel()//取消掉以前的长连接
//                    InitSocketThread().start()//创建一个新的连接
////                    } else {//长连接处于连接状态
////
////                    }
//                    sendTime = System.currentTimeMillis()
//                }
////                mHandler.postDelayed(this, HEART_BEAT_RATE)//每隔一定的时间，对长连接进行一次心跳检测
//            }
//        }
//    }
    private var isDestroy = false

    override fun onDestroy() {
        super.onDestroy()
        Log.e("eee", "onDestroy")
        //清除心跳
        clearHeart()
        isDestroy = true
        //取消廣播
        unregisterReceiver(mReceiver)
        //斷開長鏈接
        client?.let {
            mWebSocket?.cancel()
            it.dispatcher().cancelAll()
        }
        if (mWebSocket != null) {
            mWebSocket!!.send("-1")
            mWebSocket!!.close(1000, null)
        }
        //停止定時心跳
        RxTimerUtil.cancel()
        //停止前台服務
        stopForeground(true)
        //清除保持喚醒
        newWakeLock?.release()
        newWakeLock = null
    }

    private fun clearHeart() {
        val requestBody = FormBody.Builder()
                .add("restaurantId", restaurantId.toString())
                .build()
        OkHttp3Utils.post(HttpsConstans.ROOT_URL + "/member-web/api/restaurant/clearHeartbeat", requestBody)
                .subscribeOn(Schedulers.io()).subscribe()
    }

    inner class ClearHeartBroadcastReceiver : BroadcastReceiver() {
        override fun onReceive(context: Context?, intent: Intent?) {
            //關閉service，會調用service的onDestroy
            stopSelf()
        }
    }

    interface PostCallBack {
        fun callBack(type: Int)
    }

    class MsgBean(var type: Int, var token: String)

}