package com.cartrack.cartrackble

import android.app.Activity
import android.app.Dialog
import android.bluetooth.BluetoothAdapter
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.Window
import android.view.inputmethod.InputMethodManager
import android.webkit.URLUtil
import android.widget.ArrayAdapter
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.AppCompatButton
import com.cartrack.blesdk.ctg.*
import com.cartrack.blesdk.ctg.enumerations.*
import com.cartrack.getgosample.fromJson
import com.google.android.material.snackbar.Snackbar
import com.google.gson.Gson
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {

    private var test: PermissionManager? = null
    private var bleTerminal: BleTerminal? = null
    private var progressDialog: ProgressDialog? = null
    private var countryList: List<Country.Countries>? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        initSpinner()
        // val lastUsedTerminalId = getSharedPreferences().getString(LAST_USED_TERMINAL_ID, "SLD8452M")
        val lastUsedTerminalId = getSharedPreferences().getString(LAST_USED_TERMINAL_ID, "")
        et_terminal_id.setText(lastUsedTerminalId)
        progressDialog = ProgressDialog(this)
        test = PermissionManager(this)
        test?.requestPermission()



        btn_remove_key.isEnabled = getSharedPreferences().getString(AUTH_KEY, "").isNotEmpty()

        label_current_key.setText(
            "Current key: " + getSharedPreferences().getString(
                AUTH_KEY,
                "---"
            )
        )

        btn_disconnect.setOnClickListener {
            bleTerminal?.disconnect()
        }

        btn_fetch_key.setOnClickListener {
            if (!configBle()) return@setOnClickListener
            getSharedPreferences().set(LAST_USED_TERMINAL_ID, et_terminal_id.text.toString())
            progressDialog?.showProgress()
            getTerminal(et_terminal_id.text.toString())
            fetchKey()
        }
        btn_connect.setOnClickListener {
            if (!configBle()) return@setOnClickListener

            getSharedPreferences().set(LAST_USED_TERMINAL_ID, et_terminal_id.text.toString())
            if (isEnabled()) {
                progressDialog?.showProgress()
                connect(et_terminal_id.text.toString())
            } else
                checkBleState()
        }

        btn_set_base_url.setOnClickListener {
            with(et_set_url) {
                if (text.isNullOrEmpty()) {
                    error = "Please fill out"
                } else if (!URLUtil.isValidUrl(text.toString())) {
                    error = context.getString(R.string.not_valid_url)
                } else {
                    var url = text.toString()
                    if (url.last().toString() != "/") url = "$url/"
                    BleService.setApiUrl(url)
                    val imm =
                        context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
                    imm.hideSoftInputFromWindow(windowToken, 0)
                    Snackbar.make(
                        root_view,
                        context.getString(R.string.url_set_successfully),
                        Snackbar.LENGTH_SHORT
                    ).show()
                }
            }
        }
        btn_set_default_url.setOnClickListener {
            BleService.setDefaultApiUrl()
            et_set_url.setText("")
        }
        btn_get_vehicle_state.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.GET_LOCK_STATE)
        }

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

        }

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

            bleTerminal?.bleListener = bleListener
            progressDialog?.showProgress()
            bleTerminal?.randomAuthKey()
        }
        btn_remove_key.setOnClickListener {
            if (!configBle()) return@setOnClickListener
            bleTerminal?.bleListener = bleListener
            bleTerminal?.removeAuthKey()
        }

        btn_lock.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.LOCK)
        }
        btn_unlock2.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.UNLOCK_NOKEYFOB)
        }
        btn_unlock.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.UNLOCK)
        }

        btn_action_one.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.HEADLIGHT)
        }
        btn_action_two.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.HORN)
        }
        btn_ignition_state.setOnClickListener {
            progressDialog?.showProgress()
            bleTerminal?.sendAction(BleAction.VEHICLE_GET_STATUS)
        }
        btn_has_key.setOnClickListener {
            val hasKey = bleTerminal?.hasKey() ?: false
            showSnackBar("Has Key = $hasKey")
        }
    }

    fun initSpinner() {
        countryList = getCountry()
        val countryName: ArrayList<String>? = ArrayList()
        countryList?.sortedBy { it.name }?.map {
            countryName?.add(it.name.toString())
        }

        val aa = countryName?.toArray()
            ?.let { ArrayAdapter(this, android.R.layout.simple_spinner_item, it) }
        // Set layout to use when the list of choices appear
        aa?.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
        // Set Adapter to Spinner
        sp_country.setAdapter(aa)
        sp_country.setText(countryName?.find { it.contains("Singapore") }, false)
    }

    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(et_terminal_id.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 fetchKeyAndConnect() {
        bleTerminal?.prefetchAuthKey(
            onSuccess = {
                bleTerminal?.scanAndConnectToPeripheral()
                progressDialog?.showProgress()
            },
        )
    }

    private fun fetchKey() {
        bleTerminal?.fetchAuthKey()
    }

    private fun checkBleState() {
        val bluetoothAdapter = BluetoothAdapter.getDefaultAdapter()
        if (bluetoothAdapter == null || !bluetoothAdapter.isEnabled) {
            val enableBtIntent = Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE)
            startActivityForResult(enableBtIntent, REQUEST_ON_CONNECT)
        }
    }

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

    private fun enableAction() {
        btn_connect.isEnabled = false
        btn_unlock.isEnabled = true
        btn_lock.isEnabled = true
        btn_disconnect.isEnabled = true
        btn_action_one.isEnabled = true
        btn_action_two.isEnabled = true
        btn_get_vehicle_state.isEnabled = true
        btn_unlock2.isEnabled = true
        btn_vehicle_state.isEnabled = true
        btn_ignition_state.isEnabled = true
    }

    private fun disableAction() {
        btn_connect.isEnabled = true
        btn_unlock.isEnabled = false
        btn_lock.isEnabled = false
        btn_disconnect.isEnabled = false
        btn_action_one.isEnabled = false
        btn_action_two.isEnabled = false
        btn_get_vehicle_state.isEnabled = false
        btn_unlock2.isEnabled = false
        btn_vehicle_state.isEnabled = false
        btn_ignition_state.isEnabled = false

    }

    private fun showVehicleStatDialog(getVehicleStats: GetVehicleStats) {
        val dialog = Dialog(this@MainActivity)
        dialog.requestWindowFeature(Window.FEATURE_NO_TITLE)
        dialog.setCancelable(false)
        dialog.setContentView(R.layout.dialog_get_vehicle_state)
        getVehicleStats.apply {
            dialog.findViewById<TextView>(R.id.tvOdometer).text = odometer.toString()
            dialog.findViewById<TextView>(R.id.tvEngineHour).text = engineHours.toString()
            dialog.findViewById<TextView>(R.id.tvEngineRPM).text = engineRPM.toString()
            dialog.findViewById<TextView>(R.id.tvFuelLevel).text = fuelLevel.toString()
            dialog.findViewById<TextView>(R.id.tvHazards).text = hazardsIsOn.toString()
            dialog.findViewById<TextView>(R.id.tvIndicators).text = indicators.toString()
            dialog.findViewById<TextView>(R.id.tvBrakes).text = brakesIsActive.toString()
            dialog.findViewById<TextView>(R.id.tvHandBrake).text = handBrakeIsActive.toString()
            dialog.findViewById<TextView>(R.id.tvLights).text = lightsIsOn.toString()
            dialog.findViewById<TextView>(R.id.tvDriverDoor).text = driverDoorIsOpen.toString()
            dialog.findViewById<TextView>(R.id.tvPassengerDoor).text =
                passengerDoorIsOpen.toString()
            dialog.findViewById<TextView>(R.id.tvDriverSeatbelt).text =
                driverSeatbeltIsEngage.toString()
            dialog.findViewById<TextView>(R.id.tvPassengerSeatBelt).text =
                passengerSeatbeltIsEngage.toString()
            dialog.findViewById<TextView>(R.id.tvHorn).text = hornIsActive.toString()
            dialog.findViewById<AppCompatButton>(R.id.btn_back)
                .setOnClickListener { dialog.dismiss() }
        }
        dialog.show()
    }

    private fun showSnackBar(text: String) {
        Snackbar.make(
            root_view,
            text,
            Snackbar.LENGTH_SHORT
        ).show()
    }

    private val bleListener = object : BleListener {
        override fun onTerminalConnected(terminal: BleTerminal) {
            Snackbar.make(
                root_view,
                "${terminal.terminalId} Connected",
                Snackbar.LENGTH_SHORT
            ).show()

            enableAction()
            progressDialog?.dismissProgress()
        }

        override fun onTerminalCommandResult(
            action: BleAction,
        ) {
            showSnackBar("Success executing $action")
            tv_lock_state.text = "Current State: ${bleTerminal?.getLockState()}"
            progressDialog?.dismissProgress()
        }

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

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

        }

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


        override fun onTerminalDisconnected(terminal: BleTerminal) {
            Snackbar.make(
                root_view,
                "${terminal.terminalId} Disconnected",
                Snackbar.LENGTH_SHORT
            ).show()
            disableAction()
            tv_lock_state.text = "Current State: ${bleTerminal?.getLockState()}"
            progressDialog?.dismissProgress()
        }

        // WARNING: key: String?, auth key should only be for internal testing, remove it form SDK when
        // release SDK
        override fun onGetAuthKeySuccess(terminal: BleTerminal, s: String) {
            Snackbar.make(
                root_view,
                "GetAuthKey -> Success",
                Snackbar.LENGTH_SHORT
            ).show()
            getSharedPreferences().set(AUTH_KEY, s)
            label_current_key.setText("Current key: " + getSharedPreferences().getString(AUTH_KEY, "---"))
            btn_remove_key.isEnabled = getSharedPreferences().getString(AUTH_KEY, "").isNotEmpty()

            progressDialog?.dismissProgress()
        }

        override fun onRemoveAuthKeySuccess() {
            getSharedPreferences().remove(AUTH_KEY)
            label_current_key.setText(
                "Current key: " + getSharedPreferences().getString(
                    AUTH_KEY,
                    "---"
                )
            )
            btn_remove_key.isEnabled = getSharedPreferences().getString(AUTH_KEY, "").isNotEmpty()
            showSnackBar(  "RemoveKey -> Success")
            progressDialog?.dismissProgress()
        }

        override fun onRandomAuthKeySuccess(result: String) {
            showSnackBar("RandomKey -> Success ")
            progressDialog?.dismissProgress()
        }

        override fun onError(errorHandler: ErrorHandler) {
            if(progressDialog?.isShowing == true) {
                progressDialog?.dismissProgress()
            }
            showSnackBar("${errorHandler.errorCode} ${errorHandler.localizedDescription}")
        }

        override fun onSignalStrength(strength: BleSignalStrength) {
            Snackbar.make(
                root_view,
                strength.name,
                Snackbar.LENGTH_SHORT
            ).show()
        }
    }

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

    private fun getCountry(): List<Country.Countries>? {
        return Gson().fromJson<Country>(loadJSONFromAsset("country.json"))?.countries
    }

    private fun configBle(): Boolean {
        var canConfig = true
        if (sp_vendor_id.text.isNullOrEmpty()) {
            sp_vendor_id.setError("Please fill out")
            canConfig = false
        }
        if (sp_api_key.text.isNullOrEmpty()) {
            sp_api_key.setError("Please fill out")
            canConfig = false
        }
        if (et_terminal_id.text.isNullOrEmpty()) {
            et_terminal_id.setError("Please fill out")
            canConfig = false
        }
        if (!canConfig) return canConfig
        BleService.configure(
            this,
            sp_vendor_id.text.toString(),
            sp_api_key.text.toString(),
            countryList?.find { it.name == sp_country.text.toString() }?.countryCode.toString()
        )
        if (bleTerminal == null)
            bleTerminal = BleService.getTerminal(et_terminal_id.text.toString())
        return canConfig
    }

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