package com.cartrack.cartrackble

import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.app.Dialog
import android.bluetooth.BluetoothAdapter
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.view.Window
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import com.cartrack.blesdk.ctg.*
import com.cartrack.blesdk.enumerations.*
import com.cartrack.cartrackble.databinding.ActivityMainBinding
import com.cartrack.cartrackble.databinding.DialogGetVehicleStateBinding
import com.google.android.material.snackbar.Snackbar

class MainActivity : AppCompatActivity() {

    private var permissionManager: PermissionManager? = null
    private var bleTerminal: BleTerminal? = null
    private var progressDialog: ProgressDialog? = null

    private lateinit var binding: ActivityMainBinding

    @SuppressLint("SetTextI18n")
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        progressDialog = ProgressDialog(this)
        permissionManager = PermissionManager(this)
        permissionManager?.requestPermission()

        setDefaultData()
        setListener()
    }

    private fun setDefaultData() {
        val scanTimeoutDuration = getSharedPreferences().getString(SCAN_TIMER_DURATION, "10")
        val lastUsedTerminalId = getSharedPreferences().getString(LAST_USED_TERMINAL_ID, "")

        binding.btnRemoveKey.isEnabled = getSharedPreferences().getString(AUTH_KEY, "").isNotEmpty()
        binding.tvCurrentKey.text = getSharedPreferences().getString(AUTH_KEY, "---")
        binding.etScanDuration.setText(scanTimeoutDuration)
        binding.etTerminalId.setText(lastUsedTerminalId)

    }

    private fun setListener() {
        binding.apply {
            btnCreateBleTerminal.setOnClickListener {
                if (configBle().not()) return@setOnClickListener
                getAuthKey()
                showDialog("Configure BLE terminal successfully", "Success")
            }

            btnDisconnect.setOnClickListener {
                bleTerminal?.disconnect()
            }

            btnConnect.setOnClickListener {
                if (!configBle()) return@setOnClickListener

                getSharedPreferences().set(
                    LAST_USED_TERMINAL_ID,
                    binding.etTerminalId.text.toString()
                )
                if (isBluetoothEnabled()) {
                    progressDialog?.showProgress()
                    connect(binding.etTerminalId.text.toString())
                } else
                    checkBleState()
            }

            btnGetLockState.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.GET_LOCK_STATE)
            }

            btnVehicleState.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.VEHICLE_GET_CONFIG)
            }

            btnSaveKey.setOnClickListener {
                if (!checkIsConfigured()) {
                    showDialog("Please configure BLE terminal", "Warning")
                    return@setOnClickListener
                }
                saveAuthKey(binding.etNewKey.text.toString())
            }

            btnRemoveKey.setOnClickListener {
                if (!configBle()) return@setOnClickListener
                bleTerminal?.bleListener = bleListener
                removeAuthKey()
            }

            btnLock.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.LOCK)
            }
            btnUnlock2.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.UNLOCK_NOKEYFOB)
            }
            btnUnlock.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.UNLOCK)
            }

            btnActionOne.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.HEADLIGHT)
            }
            btnActionTwo.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.HORN)
            }
            btnIgnitionState.setOnClickListener {
                progressDialog?.showProgress()
                bleTerminal?.sendAction(BleAction.VEHICLE_GET_STATUS)
            }
            //        binding.btnHasKey.setOnClickListener {
            //            val hasKey = bleTerminal?.hasKey() ?: false
            //            showSnackBar("Has Key = $hasKey")
            //        }
        }
    }

    override fun onPause() {
        bleTerminal?.disconnect()
        disableAction()
        progressDialog?.hide()
        super.onPause()
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            REQUEST_ON_CONNECT -> {
                if (resultCode == Activity.RESULT_OK) {
                    connect(binding.etTerminalId.text.toString())
                }
            }
        }

        super.onActivityResult(requestCode, resultCode, data)
    }

    private fun connect(terminalId: String) {
        getTerminal(terminalId)
        scanAndConnect()
        /*  if (bleTerminal?.hasKey() == true) {
              scanAndConnect()
          } else {
              fetchKeyAndConnect()
          }*/
    }

    private fun scanAndConnect() {
        bleTerminal?.scanAndConnectToPeripheral()
    }

    private fun getTerminal(terminalId: String) {
        bleTerminal = BleService.getTerminal(terminalId)
        bleTerminal?.bleListener = bleListener
    }

    private fun getAuthKey() {
        val authKey = bleTerminal?.getAuthKey()
        if (!authKey.isNullOrEmpty()) {
            binding.tvCurrentKey.text = authKey
            binding.btnRemoveKey.isEnabled = true
        }
    }

    /**
     * Check is Ble configured
     *
     */
    private fun checkIsConfigured(): Boolean {
        return BleService.isConfigured()
    }

    private fun checkBleState() {
        if (ActivityCompat.checkSelfPermission(
                this,
                Manifest.permission.BLUETOOTH_CONNECT
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            showToast("Please allow bluetooth permission")
            return
        }
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled) {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)

            startActivityForResult(enableBtIntent, REQUEST_ON_CONNECT)
        }
    }

    private fun isBluetoothEnabled(): Boolean {
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        return bluetoothAdapter.isEnabled
    }

    /**
     * Encrypt auth key and save it to Shared Preferences
     *
     * @param key
     */
    private fun saveAuthKey(key: String) {
        bleTerminal?.saveAuthKey(key)
    }

    /**
     * Remove auth key from Shared Preferences
     *
     */
    private fun removeAuthKey() {
        bleTerminal?.removeAuthKey()
    }

    private fun enableAction() {
        binding.apply {
            btnConnect.isEnabled = false
            btnGetLockState.isEnabled = true
            btnUnlock.isEnabled = true
            btnLock.isEnabled = true
            btnDisconnect.isEnabled = true
            btnActionOne.isEnabled = true
            btnActionTwo.isEnabled = true
            btnVehicleState.isEnabled = true
            btnUnlock2.isEnabled = true
            btnVehicleState.isEnabled = true
            btnIgnitionState.isEnabled = true
        }
    }

    private fun disableAction() {
        binding.apply {
            btnConnect.isEnabled = true
            btnGetLockState.isEnabled = false
            btnUnlock.isEnabled = false
            btnLock.isEnabled = false
            btnDisconnect.isEnabled = false
            btnActionOne.isEnabled = false
            btnActionTwo.isEnabled = false
            btnVehicleState.isEnabled = false
            btnUnlock2.isEnabled = false
            btnVehicleState.isEnabled = false
            btnIgnitionState.isEnabled = false
        }
    }

    private fun showVehicleStatDialog(getVehicleStats: GetVehicleStats) {
        val dialog = Dialog(this@MainActivity)
        val dialogBinding = DialogGetVehicleStateBinding.inflate(layoutInflater)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setCancelable(false)
        dialog.setContentView(dialogBinding.root)
        getVehicleStats.apply {
            dialogBinding.apply {
                tvOdometer.text = odometer.toString()
                tvEngineHour.text = engineHours.toString()
                tvEngineRPM.text = engineRPM.toString()
                tvFuelLevel.text = fuelLevel.toString()
                tvHazards.text = hazardsIsOn.toString()
                tvIndicators.text = indicators.toString()
                tvBrakes.text = brakesIsActive.toString()
                tvHandBrake.text = handBrakeIsActive.toString()
                tvLights.text = lightsIsOn.toString()
                tvDriverDoor.text = driverDoorIsOpen.toString()
                tvPassengerDoor.text = passengerDoorIsOpen.toString()
                tvDriverSeatbelt.text = driverSeatbeltIsEngage.toString()
                tvPassengerSeatBelt.text = passengerSeatbeltIsEngage.toString()
                tvHorn.text = hornIsActive.toString()
                btnBack.setOnClickListener { dialog.dismiss() }
            }
        }
        dialog.show()
    }

    /**
     * Show message in dialog
     *
     * @param text
     * @param title
     */
    private fun showDialog(text: String, title: String = "") {
        AlertDialog.Builder(this)
            .setTitle(title)
            .setMessage(text)
            .setPositiveButton(
                "OK"
            ) { dialog, _ ->
                dialog.dismiss()
            }
            .show()
    }

    /**
     * Show message in Toast
     *
     * @param text
     */
    private fun showToast(text: String) {
        Toast.makeText(this, text, Toast.LENGTH_SHORT).show()
    }

    /**
     * Callback of bleListener
     */
    private val bleListener = object : BleListener {
        override fun onTerminalConnected(terminal: BleTerminal) {
            Snackbar.make(
                binding.rootView,
                "${terminal.terminalId} Connected",
                Snackbar.LENGTH_SHORT
            ).show()

            enableAction()
            progressDialog?.dismissProgress()
        }

        @SuppressLint("SetTextI18n")
        override fun onTerminalCommandResult(
            action: BleAction,
        ) {
            showToast("Success executing $action")
            binding.tvLockState.text = "Current State: ${bleTerminal?.getLockState()}"
            progressDialog?.dismissProgress()
        }

        override fun onTerminalDidGetVehicleStats(command: Byte, getVehicleStats: GetVehicleStats) {
            progressDialog?.dismissProgress()
            try {
                showVehicleStatDialog(getVehicleStats)
            } catch (e: Exception) {

                Snackbar.make(
                    binding.rootView,
                    e.message.toString(),
                    Snackbar.LENGTH_SHORT
                ).show()
            }

        }

        override fun onTerminalDidGetVehicleStatus(
            command: Byte,
            getVehicleStatus: GetVehicleStatus
        ) {
            progressDialog?.dismissProgress()
            Snackbar.make(
                binding.rootView,
                "Ignition State = " + if (getVehicleStatus.ignitionState == true) "On" else "Off",
                Snackbar.LENGTH_SHORT
            ).show()
        }


        @SuppressLint("SetTextI18n")
        override fun onTerminalDisconnected(terminal: BleTerminal) {
            Snackbar.make(
                binding.rootView,
                "${terminal.terminalId} Disconnected",
                Snackbar.LENGTH_SHORT
            ).show()
            disableAction()
            binding.tvLockState.text = "Current State: ${bleTerminal?.getLockState()}"
            progressDialog?.dismissProgress()
        }

        override fun onSaveAuthKeySuccess(terminal: BleTerminal, authKey: String) {
            showDialog("Save Auth Key Successfully", "Success")
            binding.apply {
                btnRemoveKey.isEnabled = true
                tvCurrentKey.text = authKey
            }
            progressDialog?.dismissProgress()
        }

        @SuppressLint("SetTextI18n")
        override fun onRemoveAuthKeySuccess() {
            getSharedPreferences().remove(AUTH_KEY)
            val authKey = getSharedPreferences().getString(AUTH_KEY, "---")
            binding.apply {
                tvCurrentKey.text = authKey
                btnRemoveKey.isEnabled = authKey.isNotEmpty()
            }
            showDialog("Remove Auth Key Successfully", "Success")
            progressDialog?.dismissProgress()
        }

        override fun onError(bleError: BleError) {
            if (progressDialog?.isShowing == true) {
                progressDialog?.dismissProgress()
            }
            if (bleError is BleError.CtgError && bleError.actionCode != -1) {
                showDialog(
                    "Error Code:${bleError.errorCode}\n${bleError.localizedDescription}\nAction Code: ${bleError.actionCode}",
                    bleError.javaClass.simpleName
                )
            } else showDialog(
                "Error Code: ${bleError.errorCode}\n${bleError.localizedDescription}",
                bleError.javaClass.simpleName
            )
        }

        override fun onSignalStrength(strength: BleSignalStrength) {
            showToast(strength.name)
        }
    }

    private fun getSharedPreferences(): PreferenceManager {
        return LocalPreferenceManager(
            getSharedPreferences(
                "com.cartrack.getgosample.prefs",
                Activity.MODE_PRIVATE
            )
        )
    }

    /**
     * Config Ble (must call before connect to Ble)
     *
     */
    private fun configBle(): Boolean {
        if (binding.etTerminalId.text.isNullOrEmpty()) {
            binding.etTerminalId.setError("Please fill out")
            return false
        }
        BleService.configure(this)
        if (bleTerminal == null) {
            bleTerminal = BleService.getTerminal(binding.etTerminalId.text.toString())
            bleTerminal?.bleListener = bleListener
        }
        return true
    }

    companion object {
        private const val REQUEST_ON_CONNECT = 101
        private const val LAST_USED_TERMINAL_ID = "lastUsedTerminalId"
        private const val AUTH_KEY = "authKey"
        private const val SCAN_TIMER_DURATION = "scanTimerDuration"
    }
}
