package com.sinch.android.rtc.sample.push

import android.Manifest
import android.app.Activity
import android.content.ComponentName
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.os.*
import android.view.Window
import android.view.WindowManager
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.sinch.android.rtc.SinchError

abstract class BaseActivity : Activity(), ServiceConnection {

    protected var sinchServiceInterface: SinchService.SinchServiceInterface? = null
        private set

    private val messenger = Messenger(object : Handler() {
        override fun handleMessage(msg: Message) {
            when (msg.what) {
                SinchService.MESSAGE_PERMISSIONS_NEEDED -> {
                    val requiredPermission = msg.data.getString(SinchService.REQUIRED_PERMISSION)
                    ActivityCompat.requestPermissions(
                        this@BaseActivity, arrayOf(
                            requiredPermission,
                            Manifest.permission.POST_NOTIFICATIONS
                        ), 0
                    )
                }
                else -> {}
            }
        }
    })

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        bindService()
        requestWindowFeature(Window.FEATURE_NO_TITLE)
        window.addFlags(
            WindowManager.LayoutParams.FLAG_FULLSCREEN
                    or WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    or WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
        )
    }

    override fun onResume() {
        super.onResume()
        attachOnSinchClientFailedCallback()
    }

    override fun onPause() {
        super.onPause()
        sinchServiceInterface?.removeOnSinchClientFailedCallback()
    }

    override fun onServiceConnected(componentName: ComponentName, iBinder: IBinder) {
        if (SinchService::class.java.name == componentName.className) {
            sinchServiceInterface = iBinder as SinchService.SinchServiceInterface
            attachOnSinchClientFailedCallback()
            onServiceConnected()
        }
    }

    protected open fun onServiceConnected() {
        // for subclasses
    }

    protected open fun onSinchClientFailed(error: SinchError) {
        Toast.makeText(this, error.toString(), Toast.LENGTH_LONG).show()
        startActivity(Intent(this, LoginActivity::class.java).apply {
            flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
        })
    }

    override fun onServiceDisconnected(componentName: ComponentName) {
        if (SinchService::class.java.name == componentName.className) {
            sinchServiceInterface = null
        }
    }

    override fun onRequestPermissionsResult(
        requestCode: Int, permissions: Array<String>,
        grantResults: IntArray
    ) {
        if (areAllPermissionsGranted(grantResults)) {
            Toast.makeText(this, "You may now place a call", Toast.LENGTH_LONG).show()
        } else {
            Toast.makeText(
                this,
                "This application needs permission to use your microphone and camera to function "
                        + "properly.",
                Toast.LENGTH_LONG
            ).show()
        }
        sinchServiceInterface?.retryStartAfterPermissionGranted()
    }

    fun areAllPermissionsGranted(grantResults: IntArray): Boolean {
        var granted = grantResults.isNotEmpty()
        for (grantResult in grantResults) {
            granted = granted and (grantResult == PackageManager.PERMISSION_GRANTED)
        }
        return granted
    }

    private fun bindService() {
        val serviceIntent = Intent(this, SinchService::class.java).apply {
            putExtra(SinchService.MESSENGER, messenger)
        }
        applicationContext.bindService(serviceIntent, this, BIND_AUTO_CREATE)
    }

    private fun attachOnSinchClientFailedCallback() {
        sinchServiceInterface?.setOnSinchClientFailedCallback {
            onSinchClientFailed(it)
        }
    }

}
