package com.gingersoft.gsa.cloud.common.service

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.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.billy.cc.core.component.CC
import com.gingersoft.gsa.cloud.common.R
import com.gingersoft.gsa.cloud.common.constans.AppConstans
import com.gingersoft.gsa.cloud.common.constans.HttpsConstans
import com.gingersoft.gsa.cloud.common.core.restaurant.RestaurantInfoManager
import com.gingersoft.gsa.cloud.common.core.user.UserContext
import com.gingersoft.gsa.cloud.common.logan.LoganManager
import com.gingersoft.gsa.cloud.common.utils.SoundPoolUtils
import com.gingersoft.gsa.cloud.common.utils.okhttpUtils.OkHttp3Utils
import com.gingersoft.gsa.cloud.common.utils.time.TimeUtils
import com.gingersoft.gsa.cloud.component.ComponentName
import com.google.gson.Gson
import com.jess.arms.utils.DeviceUtils
import com.xuexiang.rxutil2.rxjava.RxJavaUtils
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.*
import okio.ByteString
import org.json.JSONObject
import java.util.*
import java.util.concurrent.TimeUnit

class ICommandService : Service() {
    private val TAG = "heart"

    /**
     * 心跳检测时间
     */
    private val heartBeatRate = 30L//每隔30秒进行一次对长连接的心跳检测

    private val warningTime = 60L//超過六十秒還未重連，報警推送

    /**
     * 可替换为自己的主机名和端口号
     */
    private val webSocketHostPort = "${HttpsConstans.ROOT_URL}/ricepon-websocket/android/webSocketServer"

    /**
     * 長連接
     */
    private var mWebSocket: WebSocket? = null

    /**
     * 長連接客戶端
     */
    private var client: OkHttpClient? = null

    /**
     * 回調接口
     */
    var postCallBack: PostCallBack? = null

    /**
     * 關閉心跳的廣播，收到廣播註銷掉Service
     */
    private var mReceiver: ClearHeartBroadcastReceiver? = null

    /**
     * 電源喚醒
     */
    private var newWakeLock: PowerManager.WakeLock? = null
    private var myBind: MyBind? = null

    /**
     * 通知渠道id
     */
    private val CHANNEL_ID = "cloud_gsa"

    private var isCreate = false

    /**
     * 報警定時，超過一分鐘長連接未連接上，就會發送推送警報
     */
    var warningDelay: Disposable? = null

    /**
     * 心跳輪詢
     */
    var heartPolling: Disposable? = null

    /**
     * prj數據
     */
    private val PRJ_DATA = 10

    /**
     * 餐檯數據
     */
    private val TABLE_DATA = 11

    /**
     * 上次播報的時間
     */
    private var lastSoundTime: Long = 0L

    private val NOMAL_NOTIFITY_ID = 456
    private val DELIVETY_NOTIFITY_ID = 123

    companion object {
        @kotlin.jvm.JvmField
        var loginfo = StringBuffer()


        @kotlin.jvm.JvmField
        val CONNECTION_TYPE = "connection_type"

        /**
         * 开启外送接单长连
         */
        @kotlin.jvm.JvmField
        val OPEN_DELIVET_ORDER_CONNECTION = 2

        /**
         * 开启数据接收长连（prj,餐台数据）
         */
        @kotlin.jvm.JvmField
        val OPEN_OTHER_CONNECTION = 1

        /**
         * 当前连接类型
         */
        @kotlin.jvm.JvmField
        var mCurrConnectionType = OPEN_OTHER_CONNECTION
    }

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


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

        InitSocketThread().start()
        isDestroy = false
        putTimeLog("創建服務onCreate")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        //获取当前长连类型
        intent?.let {
            mCurrConnectionType = it.getIntExtra(CONNECTION_TYPE, OPEN_DELIVET_ORDER_CONNECTION)
        }
        initNotification()
        if (isCreate) {
            send(mCurrConnectionType)
        }
        isCreate = true
        putTimeLog("啟動服務onStartCommand")
        return super.onStartCommand(intent, flags, startId)
    }

    private fun initNotification() {
        if (mCurrConnectionType == OPEN_DELIVET_ORDER_CONNECTION) {
            // 在API11之后构建Notification的方式
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel(DELIVETY_NOTIFITY_ID)
            } else {
                startNotification(DELIVETY_NOTIFITY_ID)
            }
        } else {
            // 在API11之后构建Notification的方式
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                createNotificationChannel(NOMAL_NOTIFITY_ID)
            } else {
                startNotification(NOMAL_NOTIFITY_ID)
            }
        }
    }

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

    private fun startNotification(notifiyId: Int) {
        val broadcastReceiver = Intent(AppConstans.CLEAR_ORDER_RECEIVING_HEART)
        val broadcastIntent = PendingIntent.getBroadcast(this, 10, broadcastReceiver, 0)

        var remoteViews: RemoteViews

        if (notifiyId == DELIVETY_NOTIFITY_ID) {
            remoteViews = RemoteViews(packageName, R.layout.notifity_remote_order_receiving)
            remoteViews.setOnClickPendingIntent(R.id.btn_stop_service, broadcastIntent)
        } else {
            remoteViews = RemoteViews(packageName, R.layout.notifity_remote_receive_command)
        }

        //在创建的通知渠道上发送通知
        val builder = NotificationCompat.Builder(this, CHANNEL_ID)
        builder.setSmallIcon(R.mipmap.ic_launcher) //设置通知图标
        builder.setContentTitle("Ricepon POS")//设置通知标题
        builder.setContentText("connection service")//设置通知内容

        val pendingIntent: PendingIntent
        if (notifiyId == DELIVETY_NOTIFITY_ID) {
            var intent: Intent? = null
            myBind?.jumpActivity?.let {
                intent = Intent(this, it)
            }
            if (intent == null) {
                intent = Intent("action.gingersoft.DELIVERY_ORDER")
            }
            pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
            builder.setContentIntent(pendingIntent)
        }
        builder.setContent(remoteViews)
        builder.setAutoCancel(false) //用户触摸时，自动关闭
        builder.setOngoing(true)//设置处于运行状态
        builder.setLargeIcon(BitmapFactory.decodeResource(resources, R.mipmap.ic_launcher))
        //将服务置于启动状态 NOTIFICATION_ID指的是创建的通知的ID
        startForeground(notifiyId, builder.build())
        if (!UserContext.newInstance().isLogin) {
            stopSelf()
            return
        }
    }

    fun restartNotification() {
        mCurrConnectionType = OPEN_OTHER_CONNECTION;
        //先停止前台服務
        stopForeground(true)
        // 在API11之后构建Notification的方式
        initNotification()
    }

    inner class MyBind : Binder() {
        lateinit var block: (isShow: Boolean) -> Unit
        var jumpActivity: Class<*>? = null
            set(value) {
                field = value
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                    createNotificationChannel(DELIVETY_NOTIFITY_ID)
                } else {
                    startNotification(DELIVETY_NOTIFITY_ID)
                }
            }

        fun setOnPostCallBack(postCallBack: PostCallBack?) {
            this@ICommandService.postCallBack = postCallBack
        }

        fun execute(block: (isShow: Boolean) -> Unit) {
            this.block = block
        }
    }

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

    // 初始化socket
    private fun initSocket() {
        putTimeLog("initSocket開始輪詢")
        heartPolling?.dispose()
        heartPolling = RxJavaUtils.polling(0, heartBeatRate) {
            run {
                //保持設備喚醒
                newWakeLock?.acquire(10 * 60 * 1000L /*10 minutes*/)
                //先斷開之前的
                client?.let { it ->
                    mWebSocket?.let {
                        it.cancel()
                        it.send("-1")
                        it.close(1000, "手動斷開")
                        putTimeLog("開啟之前先斷開心跳")
                    }
                    it.dispatcher().cancelAll()
                }
                client = OkHttpClient.Builder().readTimeout(9 * 10, TimeUnit.SECONDS).build()
                client?.let {
                    val request = Request.Builder()
                            .url(webSocketHostPort)
                            .build()
                    it.newWebSocket(request, object : WebSocketListener() {
                        override fun onOpen(webSocket: WebSocket, response: Response) {//开启长连接成功的回调
                            super.onOpen(webSocket, response)
                            if (!this@ICommandService.isDestroy) {
                                mWebSocket = webSocket
                                send(mCurrConnectionType)
                                putTimeLog("onOpen心跳連接成功")
                                warningDelay?.dispose()
                                myBind?.block?.invoke(false)
                            }
                        }

                        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)
                            }
                            //收到服务器端传过来的消息text
                            putTimeLog("onMessage收到回調：$text")
                            //-1斷開連接,
                            // \n-2:消息傳輸錯誤,
                            // \n0:連接消息,
                            // \n1：登錄通知,
                            // \n2：登出通知,
                            // \n3：外賣送單通知,
                            // \n4：自取送單通知,
                            // \n5:歷史訂單通知,
                            // \n6:修改訂單狀態通知,
                            // \n7:支付成功通知"
                            // 10:prj数据
                            // 11:餐台数据
                            if (type == 3 || type == 4 || type == 5 || type == 7) {
                                //播放提示音
                                initSoundPool(R.raw.newordervocal)
                            } else if (type == 8) {
                                initSoundPool(R.raw.raw_logistics_cancel)
                            } else if (type == PRJ_DATA) {
                                CC.obtainBuilder(ComponentName.COMPONENT_PRINT)
                                        .setActionName("getPrjData")
                                        .build()
                                        .call()
                            } else if (type == TABLE_DATA) {
                                CC.obtainBuilder(ComponentName.COMPONENT_TABLE)
                                        .setActionName("getTables")
                                        .build()
                                        .call()
                            }
                        }

                        override fun onMessage(webSocket: WebSocket, bytes: ByteString) {
                            super.onMessage(webSocket, bytes)
                            val json = JSONObject(bytes.toString())
                            putTimeLog("收到消息onMessage：$bytes")
                            if (postCallBack != null) {
                                postCallBack!!.callBack(json.optInt("type"))
                            }
                        }

                        override fun onClosing(webSocket: WebSocket, code: Int, reason: String) {
                            super.onClosing(webSocket, code, reason)
                            //連接斷開，
                            putTimeLog("onClosing關閉連接，code：$code——reason：$reason")
                        }

                        override fun onClosed(webSocket: WebSocket, code: Int, reason: String) {
                            super.onClosed(webSocket, code, reason)
                            putTimeLog("onClosed斷開連接，Code：$code——reason：$reason")
                            webSocket.cancel()
                        }

                        override fun onFailure(webSocket: WebSocket, t: Throwable, response: Response?) {//长连接连接失败的回调
                            super.onFailure(webSocket, t, response)
                            putTimeLog("onFailure連接失敗，——reason：$t")
                            if (!this@ICommandService.isDestroy) {
                                //連接斷開，定時五秒，如果未重連，播放提示音
                                putTimeLog("onFailure連接失敗，延時任務狀態${warningDelay?.isDisposed}")
                                if (warningDelay == null || warningDelay!!.isDisposed) {
                                    warningDelay = RxJavaUtils.delay(warningTime) {
                                        putTimeLog("執行心跳斷開六十秒報警延時任務")
                                        initSoundPool(R.raw.raw_disconnect)
                                        myBind?.block?.invoke(true)
                                        //推送給相關人員
                                        OkHttp3Utils.noticePersonnel(AppConstans.RP_HEART_ERROR, "心跳斷開六十秒以上未連接成功：" + t.message)
                                    }
                                    putTimeLog("onFailure連接失敗，開始等待一分鐘後重新連接")
                                }
                            } else {
                                webSocket.cancel()
                                it.dispatcher().cancelAll()
                            }
                        }
                    })
                    it.dispatcher().executorService().shutdown()
                }
            }
        }
    }

    fun send(currConnectionType: Int) {
//        val token = "weixin_" + RestaurantInfoManager.newInstance().restaurantId + "_" + UserContext.newInstance().memberId + "_" + getRandomString(24)
        val token = "weixin_" + RestaurantInfoManager.newInstance().restaurantId + "_" + getRandomString(24)
        LoganManager.w_code(TAG, "token=$token")
        if (mWebSocket != null) {
            mWebSocket?.send(Gson().toJson(MsgBean(1, getConnectiontype(), token, UserContext.newInstance().memberId, DeviceUtils.getDeviceId(this))))
        }
    }

    private fun getConnectiontype(): String {
        var connectiontype = "$OPEN_OTHER_CONNECTION"
        if (mCurrConnectionType == OPEN_DELIVET_ORDER_CONNECTION) {
            connectiontype = "$OPEN_OTHER_CONNECTION , $OPEN_DELIVET_ORDER_CONNECTION"
        }
        return connectiontype
    }

    /**
     * 初始化SoundPool
     */
    fun initSoundPool(resId: Int) {
        val nowTime = System.currentTimeMillis()//當前時間減去上次播放的時間，如果超過五秒，那麼才會再次播放提示聲
        if (nowTime - lastSoundTime > 5000) {
            putTimeLog("現在時間：$nowTime 上次播放時間：$lastSoundTime")
            putTimeLog("新訂單播放：$nowTime")
            lastSoundTime = nowTime
            SoundPoolUtils.initSoundPool(this, resId)
        }
    }

    /**
     * 获取一条随机字符串
     * @param length 表示生成字符串的长度
     */
    private fun getRandomString(length: Int): String {
        val base = "abcdefghijklmnopqrstuvwxyz0123456789"
        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 isDestroy = false

    override fun onDestroy() {
        super.onDestroy()
        clearTask()
    }

    private fun clearTask() {
        putTimeLog("服務銷毀onDestroy")
        //清除心跳
        clearHeart()
        isDestroy = true
        //取消廣播
        mReceiver?.let {
            unregisterReceiver(mReceiver)
            mReceiver = null
        }
        //斷開長鏈接
        client?.let {
            mWebSocket?.cancel()
            it.dispatcher().cancelAll()
        }
        if (mWebSocket != null) {
            mWebSocket!!.send("-1")
            mWebSocket!!.close(1000, null)
        }
        //停止定時心跳
        heartPolling?.dispose()
        //停止延遲執行任務
        warningDelay?.dispose()
        //停止前台服務
        stopForeground(true)
        //清除保持喚醒
        newWakeLock?.release()
        newWakeLock = null
    }

    private fun clearHeart() {
        val requestBody = FormBody.Builder()
                .add("restaurantId", RestaurantInfoManager.newInstance().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()
            restartNotification()
            send(mCurrConnectionType)
        }
    }

    /**
     * 向日誌添加數據
     */
    private fun putTimeLog(content: String) {
        loginfo.append(TimeUtils.getCurrentDate(TimeUtils.DEFAULT_DATE_FORMAT))
        loginfo.append("：")
        loginfo.append(content)
        loginfo.append("\n")
        LoganManager.w_network("$TAG -> $content")
    }

    class MsgBean(var type: Int, var data: String, var token: String, var userId: Int, var deviceId: String)

}