package com.google.chip.chiptool.clusterclient

import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.view.inputmethod.EditorInfo
import android.widget.ArrayAdapter
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ReportCallback
import chip.devicecontroller.WriteAttributesCallback
import chip.devicecontroller.model.AttributeWriteRequest
import chip.devicecontroller.model.ChipAttributePath
import chip.devicecontroller.model.ChipEventPath
import chip.devicecontroller.model.NodeState
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.GenericChipDeviceListener
import com.google.chip.chiptool.R
import com.google.chip.chiptool.databinding.BasicClientFragmentBinding
import com.google.chip.chiptool.util.TlvParseUtil
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import java.util.Optional

import chip.devicecontroller.ClusterIDMapping.*

class BasicClientFragment : Fragment() {
  private val deviceController: ChipDeviceController
    get() = ChipClient.getDeviceController(requireContext())

  private lateinit var scope: CoroutineScope

  private lateinit var addressUpdateFragment: AddressUpdateFragment

  private var _binding: BasicClientFragmentBinding? = null
  private val binding get() = _binding!!

  override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
  ): View {
    _binding = BasicClientFragmentBinding.inflate(inflater, container, false)
    scope = viewLifecycleOwner.lifecycleScope

    deviceController.setCompletionListener(ChipControllerCallback())

    addressUpdateFragment =
      childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment
    binding.writeNodeLabelBtn.setOnClickListener { scope.launch {
      // TODO : Need to be implement poj-to-tlv
      sendWriteAttribute(BasicInformation.Attribute.NodeLabel, TlvParseUtil.encode(binding.nodeLabelEd.text.toString()))
      binding.nodeLabelEd.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }}
    binding.writeLocationBtn.setOnClickListener { scope.launch {
      // TODO : Need to be implement poj-to-tlv
      sendWriteAttribute(BasicInformation.Attribute.Location, TlvParseUtil.encode(binding.locationEd.text.toString()))
      binding.locationEd.onEditorAction(EditorInfo.IME_ACTION_DONE)
    }}
    binding.writeLocalConfigDisabledSwitch.setOnCheckedChangeListener { _, isChecked ->
      scope.launch {
        // TODO : Need to be implement poj-to-tlv
        sendWriteAttribute(BasicInformation.Attribute.LocalConfigDisabled, TlvParseUtil.encode(isChecked))
      }
    }
    makeAttributeList()
    binding.attributeNameSpinner.adapter = makeAttributeNamesAdapter()
    binding.readAttributeBtn.setOnClickListener { scope.launch { readAttributeButtonClick() }}

    return binding.root
  }

  override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
  }

  inner class ChipControllerCallback : GenericChipDeviceListener() {
    override fun onConnectDeviceComplete() {}

    override fun onCommissioningComplete(nodeId: Long, errorCode: Int) {
      Log.d(TAG, "onCommissioningComplete for nodeId $nodeId: $errorCode")
    }

    override fun onNotifyChipConnectionClosed() {
      Log.d(TAG, "onNotifyChipConnectionClosed")
    }

    override fun onCloseBleComplete() {
      Log.d(TAG, "onCloseBleComplete")
    }

    override fun onError(error: Throwable?) {
      Log.d(TAG, "onError: $error")
    }
  }


  private fun makeAttributeNamesAdapter(): ArrayAdapter<String> {
    return ArrayAdapter(
      requireContext(),
      android.R.layout.simple_spinner_dropdown_item,
      ATTRIBUTES.toList()
    ).apply {
      setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
    }
  }

  private suspend fun readAttributeButtonClick() {
    try {
      readBasicClusters(binding.attributeNameSpinner.selectedItemPosition)
    } catch (ex: Exception) {
      showMessage("readBasicCluster failed: $ex")
    }
  }

  private suspend fun readBasicClusters(itemIndex: Int) {
    val endpointId = addressUpdateFragment.endpointId
    val clusterId = BasicInformation.ID
    val attributeName = ATTRIBUTES[itemIndex]
    val attributeId = BasicInformation.Attribute.valueOf(attributeName).id

    val devicePtr = ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)

    ChipClient.getDeviceController(requireContext()).readPath(object: ReportCallback {
      override fun onError(attributePath: ChipAttributePath?, eventPath: ChipEventPath?, ex: java.lang.Exception) {
        showMessage("Read $attributeName failure $ex")
        Log.e(TAG, "Read $attributeName failure", ex)
      }

      override fun onReport(nodeState: NodeState?) {
        val value = nodeState?.getEndpointState(endpointId)?.getClusterState(clusterId)?.getAttributeState(attributeId)?.value ?: "null"
        Log.i(TAG,"[Read Success] $attributeName: $value")
        showMessage("[Read Success] $attributeName: $value")
      }

    }, devicePtr, listOf(ChipAttributePath.newInstance(endpointId, clusterId, attributeId)), null, false, 0 /* imTimeoutMs */)
  }

  private fun makeAttributeList() {
    for (attribute in BasicInformation.Attribute.values()) {
      ATTRIBUTES.add(attribute.name)
    }
  }

  private suspend fun sendWriteAttribute(attribute: BasicInformation.Attribute, tlv: ByteArray) {
    val clusterId = BasicInformation.ID
    val devicePtr = ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)

    ChipClient.getDeviceController(requireContext()).write(object: WriteAttributesCallback {
      override fun onError(attributePath: ChipAttributePath?, ex: java.lang.Exception?) {
        showMessage("Write ${attribute.name} failure $ex")
        Log.e(TAG, "Write ${attribute.name} failure", ex)
      }

      override fun onResponse(attributePath: ChipAttributePath?) {
        showMessage("Write ${attribute.name} success")
      }

    }, devicePtr, listOf(AttributeWriteRequest.newInstance(addressUpdateFragment.endpointId, clusterId, attribute.id, tlv, Optional.empty())), 0, 0)
  }

  private fun showMessage(msg: String) {
    requireActivity().runOnUiThread {
      binding.basicClusterCommandStatus.text = msg
    }
  }

  override fun onResume() {
    super.onResume()
    addressUpdateFragment.endpointId = ENDPOINT
  }

  companion object {
    private const val TAG = "BasicClientFragment"
    private const val ENDPOINT = 0
    private val ATTRIBUTES: MutableList<String> = mutableListOf()

    fun newInstance(): BasicClientFragment = BasicClientFragment()
  }
}
