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

import android.Manifest
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.util.Log
import android.view.View
import android.widget.Button
import android.widget.TextView
import android.widget.Toast
import androidx.core.app.ActivityCompat
import com.sinch.android.rtc.calling.Call
import com.sinch.android.rtc.calling.CallListener

class IncomingCallScreenActivity : BaseActivity() {

    private lateinit var answerButton: Button
    private lateinit var declineButton: Button
    private lateinit var remoteUserTextView: TextView

    private val callId: String get() = intent.getStringExtra(SinchService.CALL_ID).orEmpty()
    private val call: Call? get() = sinchServiceInterface?.getCall(callId)
    private val audioPlayer: AudioPlayer by lazy {
        AudioPlayer(this)
    }
    private val action: String? get() = intent.action

    private val mClickListener = View.OnClickListener { view ->
        when (view.id) {
            R.id.answerButton -> answerCall()
            R.id.declineButton -> declineClicked()
            else -> {}
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.incoming)
        answerButton = findViewById(R.id.answerButton)
        declineButton = findViewById(R.id.declineButton)
        remoteUserTextView = findViewById(R.id.remoteUser)

        answerButton.setOnClickListener(mClickListener)
        declineButton.setOnClickListener(mClickListener)
        audioPlayer.playIncomingRingtone()
    }

    override fun onServiceConnected() {
        val call = call
        if (call != null) {
            call.addCallListener(SinchCallListener())
            remoteUserTextView.text = call.remoteUserId
            if (ACTION_ANSWER == action) {
                answerCall()
            } else if (ACTION_IGNORE == action) {
                declineClicked()
            }
        } else {
            Log.e(TAG, "Started with invalid callId, aborting")
            finish()
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (areAllPermissionsGranted(grantResults)) {
            answerCall()
        } else {
            Toast.makeText(this, "Required permissions declined, cannot answer the call.", Toast.LENGTH_LONG).show()
        }
    }

    private fun answerCall() {
        val call = call
        audioPlayer.stopIncomingRingtone()
        if (call != null) {
            if (hasRequiredPermissions()) {
                Log.d(TAG, "Answering call")
                call.answer()
                val intent = Intent(this, CallScreenActivity::class.java)
                    .apply {
                        putExtra(SinchService.CALL_ID, callId)
                    }
                startActivity(intent)
            } else {
                ActivityCompat.requestPermissions(
                    this,
                    arrayOf(Manifest.permission.RECORD_AUDIO),
                    0
                )
            }
        } else {
            finish()
        }
    }

    private fun hasRequiredPermissions(): Boolean =
        checkCallingOrSelfPermission(Manifest.permission.RECORD_AUDIO) == PackageManager.PERMISSION_GRANTED

    private fun declineClicked() {
        audioPlayer.stopIncomingRingtone()
        call?.hangup()
        finish()
    }

    private inner class SinchCallListener : CallListener {

        override fun onCallEnded(call: Call) {
            val cause = call.details.endCause
            Log.d(TAG, "Call ended, cause: $cause")
            audioPlayer.stopIncomingRingtone()
            finish()
        }

        override fun onCallEstablished(call: Call) {
            Log.d(TAG, "Call established")
        }

        override fun onCallProgressing(call: Call) {
            Log.d(TAG, "Call progressing")
        }
    }

    companion object {
        private val TAG: String = IncomingCallScreenActivity::class.java.simpleName

        const val ACTION_ANSWER = "answer"
        const val ACTION_IGNORE = "ignore"
    }
}
