package com.hmg.hmgDr

import android.Manifest
import android.app.Activity
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.IBinder
import android.provider.Settings
import android.util.Log
import android.widget.Toast
import androidx.annotation.NonNull
import com.google.gson.GsonBuilder
import com.hmg.hmgDr.Service.VideoStreamFloatingWidgetService
import com.hmg.hmgDr.Model.GetSessionStatusModel
import com.hmg.hmgDr.Model.SessionStatusModel
import com.hmg.hmgDr.ui.VideoCallResponseListener
import io.flutter.embedding.android.FlutterFragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugins.GeneratedPluginRegistrant
//import pub.devrel.easypermissions.AfterPermissionGranted
//import pub.devrel.easypermissions.AppSettingsDialog
//import pub.devrel.easypermissions.EasyPermissions


class MainActivity : FlutterFragmentActivity(), MethodChannel.MethodCallHandler,
    VideoCallResponseListener {

    /*  Permission request code to draw over other apps  */
    private val DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE = 1222

    private val CHANNEL = "Dr.cloudSolution/videoCall"
    private lateinit var methodChannel: MethodChannel
    private var result: MethodChannel.Result? = null
    private var call: MethodCall? = null
    private val LAUNCH_VIDEO: Int = 1

    private var serviceIntent: Intent? = null
    private var videoStreamService: VideoStreamFloatingWidgetService? = null
    private var bound = false

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
        GeneratedPluginRegistrant.registerWith(flutterEngine)

        methodChannel = MethodChannel(flutterEngine.dartExecutor.binaryMessenger, CHANNEL)
        methodChannel.setMethodCallHandler(this)
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {

        this.result = result
        this.call = call

        when (call.method) {
            "openVideoCall" -> {
                val apiKey = call.argument<String>("kApiKey")
                val sessionId = call.argument<String>("kSessionId")
                val token = call.argument<String>("kToken")
                val appLang = call.argument<String>("appLang")
                val baseUrl = call.argument<String>("baseUrl")

                // Session Status model
                val VC_ID = call.argument<Int>("VC_ID")
                val tokenID = call.argument<String>("TokenID")
                val generalId = call.argument<String>("generalId")
                val doctorId = call.argument<Int>("DoctorId")
                val patientName = call.argument<String>("patientName")
                val isRecording = call.argument<Boolean>("isRecording")

                val sessionStatusModel =
                    GetSessionStatusModel(
                        VC_ID,
                        tokenID,
                        generalId,
                        doctorId,
                        patientName,
                        isRecording!!
                    )


                openVideoCall(apiKey, sessionId, token, appLang, baseUrl, sessionStatusModel)

            }
            "closeVideoCall" -> {
                videoStreamService?.closeVideoCall()
            }
            else -> {
                result.notImplemented()
            }
        }
    }

    private fun openVideoCall(
        apiKey: String?,
        sessionId: String?,
        token: String?,
        appLang: String?,
        baseUrl: String?,
        sessionStatusModel: GetSessionStatusModel
    ) {

        val arguments = Bundle()
        arguments.putString("apiKey", apiKey)
        arguments.putString("sessionId", sessionId)
        arguments.putString("token", token)
        arguments.putString("appLang", appLang)
        arguments.putString("baseUrl", baseUrl)
        arguments.putParcelable("sessionStatusModel", sessionStatusModel)

        // start service
//        serviceIntent = Intent(this@MainActivity, VideoStreamContainerService::class.java)
        if (videoStreamService == null || videoStreamService?.serviceRunning == false) {
            serviceIntent = Intent(this@MainActivity, VideoStreamFloatingWidgetService::class.java)
            serviceIntent?.run {
                putExtras(arguments)
                action = VideoStreamFloatingWidgetService.ACTION_START_CALL
            }
            checkFloatingWidgetPermission()
        }
    }

    private fun checkFloatingWidgetPermission() {
//        Check if the application has draw over other apps permission or not?
//        This permission is by default available for API<23. But for API > 23
//        you have to ask for the permission in runtime.
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.canDrawOverlays(this)) {
            //If the draw over permission is not available open the settings screen
            //to grant the permission.
            val intent = Intent(
                Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
                Uri.parse("package:$packageName")
            )
            startActivityForResult(intent, DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE)
        } else {  //If permission is granted start floating widget service
            startFloatingWidgetService()
        }
    }

    private fun startFloatingWidgetService() {
        startService(serviceIntent)
        bindService()
    }

    override fun onDestroy() {
        super.onDestroy()
        if (bound) {
            unbindService()
        }
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
      if (requestCode == DRAW_OVER_OTHER_APP_PERMISSION_REQUEST_CODE) {
            //Check if the permission is granted or not.
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (Settings.canDrawOverlays(this)) {
                    startFloatingWidgetService()
                } else {
                    //Permission is not available then display toast
                    Toast.makeText(
                        this,
                        "Draw over other app permission not available. App won\\'t work without permission. Please try again.",
                        Toast.LENGTH_SHORT
                    ).show()
                }
            } else {
                startFloatingWidgetService()
            }
        } else {
            super.onActivityResult(requestCode, resultCode, data)
        }
    }

    override fun onCallFinished(resultCode: Int, intent: Intent?) {
        if (resultCode == Activity.RESULT_OK) {
            val result: SessionStatusModel? = intent?.getParcelableExtra("sessionStatusNotRespond")
            val callResponse: HashMap<String, String> = HashMap()

            val sessionStatus: HashMap<String, String> = HashMap()
            val gson = GsonBuilder().serializeNulls().create()

            callResponse["callResponse"] = "CallNotRespond"
            val jsonRes = gson.toJson(result)
            callResponse["sessionStatus"] = jsonRes

            try {
                this.result?.success(callResponse)
            } catch (e: Exception) {
                Log.e("onVideoCallFinished", "${e.message}.")
            }
        } else if (resultCode == Activity.RESULT_CANCELED) {
            val callResponse: HashMap<String, String> = HashMap()
            callResponse["callResponse"] = "CallEnd"
            try {
                result?.success(callResponse)
            } catch (e: Exception) {
                Log.e("onVideoCallFinished", "${e.message}.")
            }
        }

        stopService(serviceIntent)
    }

    override fun minimizeVideoEvent(isMinimize: Boolean) {
        if (isMinimize)
            methodChannel.invokeMethod("onCallConnected", null)
        else {
            methodChannel.invokeMethod("onCallDisconnected", null)
            unbindService()
            videoStreamService?.serviceRunning = false
            videoStreamService = null
        }
    }

    override fun onBackPressed() {
        if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) {
            videoStreamService!!.onMinimizedClicked()
        } else {
            super.onBackPressed()
        }
    }

    override fun onPause() {
        if (videoStreamService != null && videoStreamService?.serviceRunning == true && videoStreamService?.isFullScreen!!) {
            videoStreamService!!.onMinimizedClicked()
        }
        super.onPause()
    }

//    override fun onStart() {
//        super.onStart()
//        bindService()
//    }
//
//    override fun onStop() {
//        super.onStop()
//        unbindService()
//    }

    private fun bindService() {
        serviceIntent?.run {
            if (videoStreamService != null && !videoStreamService!!.serviceRunning) {
                startService(this)
            }
            bindService(this, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    private fun unbindService() {
        if (bound) {
            videoStreamService?.videoCallResponseListener = null // unregister
            unbindService(serviceConnection)
            bound = false
        }
    }

    private val serviceConnection: ServiceConnection = object : ServiceConnection {
        override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
//            val binder: VideoStreamContainerService.VideoStreamBinder =
//                service as VideoStreamContainerService.VideoStreamBinder
            val binder: VideoStreamFloatingWidgetService.VideoStreamBinder =
                service as VideoStreamFloatingWidgetService.VideoStreamBinder
            videoStreamService = binder.service
            bound = true
            videoStreamService!!.videoCallResponseListener = this@MainActivity // register
            videoStreamService?.serviceRunning = true
        }

        override fun onServiceDisconnected(name: ComponentName?) {
            bound = false
        }

    }
}
