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.ClusterIDMapping.*
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 chip.devicecontroller.model.Status
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.toAny
import java.util.Optional
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
import matter.tlv.AnonymousTag
import matter.tlv.TlvReader
import matter.tlv.TlvWriter

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,
          TlvWriter().put(AnonymousTag, binding.nodeLabelEd.text.toString()).getEncoded()
        )
        binding.nodeLabelEd.onEditorAction(EditorInfo.IME_ACTION_DONE)
      }
    }
    binding.writeLocationBtn.setOnClickListener {
      scope.launch {
        // TODO : Need to be implement poj-to-tlv
        sendWriteAttribute(
          BasicInformation.Attribute.Location,
          TlvWriter().put(AnonymousTag, binding.locationEd.text.toString()).getEncoded()
        )
        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,
          TlvWriter().put(AnonymousTag, isChecked).getEncoded()
        )
      }
    }
    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: Long) {
      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 =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }

    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 tlv =
              nodeState
                ?.getEndpointState(endpointId)
                ?.getClusterState(clusterId)
                ?.getAttributeState(attributeId)
                ?.tlv
            val value = tlv?.let { TlvReader(it).toAny() }
            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 =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }

    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, status: Status) {
            showMessage("Write ${attribute.name} response: $status")
          }
        },
        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()
  }
}
