package com.sinch.android.rtc.sample.hmspush.hms

import android.app.NotificationChannel
import android.app.NotificationManager
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.os.Build
import android.os.IBinder
import android.util.Log
import com.huawei.hms.push.HmsMessageService
import com.huawei.hms.push.RemoteMessage
import com.sinch.android.rtc.SinchPush.isSinchPushPayload
import com.sinch.android.rtc.SinchPush.queryPushNotificationPayload
import com.sinch.android.rtc.calling.CallNotificationResult
import com.sinch.android.rtc.sample.hmspush.SinchService
import com.sinch.android.rtc.sample.hmspush.hms.HmsListenerService

class HmsListenerService : HmsMessageService() {

    override fun onMessageReceived(message: RemoteMessage) {
        val data = message.dataOfMap
        Log.d(TAG, "Got HMS message.")
        if (!isSinchPushPayload(data)) {
            Log.d(TAG, "Non Sinch push payload received. Ignoring.")
            return
        }
        val result = try {
            queryPushNotificationPayload(applicationContext, data)
        } catch (e: Exception) {
            Log.e(TAG, "Error while executing queryPushNotificationPayload", e)
            return
        }

        // Optional: inspect the payload w/o starting Sinch Client and thus avoiding
        // onIncomingCall() e.g. useful to fetch user related polices (blacklist),
        // resources (to show a picture, etc).
        Log.d(TAG, "queryPushNotificationPayload() -> display name: " + result.displayName)
        Log.d(TAG, "queryPushNotificationPayload() -> call headers: " + result.callHeaders)
        Log.d(TAG, "queryPushNotificationPayload() -> remote user ID: " + result.remoteUserId)

        // Mandatory: forward payload to the SinchClient.
        object : ServiceConnection {
            private var callNotificationResult: CallNotificationResult? = null

            override fun onServiceConnected(name: ComponentName, service: IBinder) {
                callNotificationResult?.let {
                    val sinchService = service as SinchService.SinchServiceInterface
                    try {
                        sinchService.relayRemotePushNotificationPayload(it)
                        // Optional: handle call notification result data, e.g. show a system
                        // notification or similar.
                    } catch (e: Exception) {
                        Log.e(TAG, "Error while executing relayRemotePushNotificationPayload", e)
                    }
                }
                callNotificationResult = null
            }

            override fun onServiceDisconnected(name: ComponentName) {}

            fun relayCallNotification(callNotificationResult: CallNotificationResult) {
                this.callNotificationResult = callNotificationResult
                createNotificationChannel(NotificationManager.IMPORTANCE_MAX)
                applicationContext.bindService(
                    Intent(applicationContext, SinchService::class.java), this,
                    BIND_AUTO_CREATE
                )
            }
        }.relayCallNotification(result)
    }

    private fun createNotificationChannel(importance: Int) {
        // Create the NotificationChannel, but only on API 26+ because
        // the NotificationChannel class is new and not in the support library
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val name: CharSequence = "Sinch"
            val description = "Incoming Sinch Push Notifications."
            val channel = NotificationChannel(CHANNEL_ID, name, importance)
            channel.description = description
            // Register the channel with the system; you can't change the importance
            // or other notification behaviors after this
            val notificationManager = getSystemService(
                NotificationManager::class.java
            )
            notificationManager.createNotificationChannel(channel)
        }
    }

    companion object {
        private val TAG = HmsListenerService::class.java.simpleName
        const val CHANNEL_ID = "Sinch Push Notification Channel"
    }
}