package com.google.chip.chiptool.clusterclient

import android.app.AlertDialog
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.ArrayAdapter
import android.widget.Button
import android.widget.EditText
import android.widget.Spinner
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipClusters
import chip.devicecontroller.ChipDeviceController
import chip.devicecontroller.ChipStructs
import chip.devicecontroller.ChipStructs.AccessControlClusterAccessControlEntryStruct
import chip.devicecontroller.ChipStructs.GroupKeyManagementClusterGroupKeySetStruct
import chip.devicecontroller.GroupKeySecurityPolicy
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.GenericChipDeviceListener
import com.google.chip.chiptool.R
import com.google.chip.chiptool.databinding.GroupSettingFragmentBinding
import com.google.chip.chiptool.util.DeviceIdUtil
import java.lang.Exception
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

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

  private lateinit var scope: CoroutineScope

  private lateinit var addressUpdateFragment: AddressUpdateFragment

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

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

    deviceController.setCompletionListener(ChipControllerCallback())

    addressUpdateFragment =
      childFragmentManager.findFragmentById(R.id.addressUpdateFragment) as AddressUpdateFragment

    binding.sendKeySetWriteBtn.setOnClickListener { sendKeySetWriteBtnClick() }
    binding.writeGroupKeyMapBtn.setOnClickListener { writeGroupKeyMapBtnClick() }
    binding.sendAddGroupBtn.setOnClickListener { sendAddGroupBtnClick() }
    binding.addAccessControlBtn.setOnClickListener { scope.launch { readAccessControl() } }
    binding.addGroupBtn.setOnClickListener { addGroupBtnClick() }
    binding.removeGroupBtn.setOnClickListener { removeGroupBtnClick() }
    binding.addkeysetBtn.setOnClickListener { addKeySetBtnClick() }
    binding.removekeysetBtn.setOnClickListener { removeKeySetBtnClick() }
    binding.bindkeysetBtn.setOnClickListener { bindKeySetBtnClick(true) }
    binding.unbindkeysetBtn.setOnClickListener { bindKeySetBtnClick(false) }

    return binding.root
  }

  private fun addGroupBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.add_group_dialog, null)
    val groupIdEd = dialogView.findViewById<EditText>(R.id.groupIdEd)
    val groupNameEd = dialogView.findViewById<EditText>(R.id.groupNameEd)

    dialogView.findViewById<Button>(R.id.sendGroupDialogBtn).visibility = View.GONE

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.addGroupDialogBtn).setOnClickListener {
      val groupId = groupIdEd.text.toString().toUInt()
      val ret = deviceController.addGroup(groupId.toInt(), groupNameEd.text.toString())
      showMessage("addGroup : $ret")
      updateGroupSettingView()
      DeviceIdUtil.setCommissionedNodeId(
        requireContext(),
        AddressUpdateFragment.getNodeIdFromGroupId(groupId).toLong()
      )
      addressUpdateFragment.updateDeviceIdSpinner()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }
    dialog.show()
  }

  private fun removeGroupBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.remove_group_dialog, null)

    val groupList = deviceController.availableGroupIds

    val groupListSp = dialogView.findViewById<Spinner>(R.id.groupListSp)
    groupListSp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        groupList.map { it.toString() }
      )

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.removeGroupDialogBtn).setOnClickListener {
      val selectedGroupId = groupListSp.selectedItem.toString().toUInt()
      val ret = deviceController.removeGroup(selectedGroupId.toInt())
      showMessage("removeGroup : $selectedGroupId - $ret")
      updateGroupSettingView()
      DeviceIdUtil.removeCommissionedNodeId(
        requireContext(),
        AddressUpdateFragment.getNodeIdFromGroupId(selectedGroupId).toLong()
      )
      addressUpdateFragment.updateDeviceIdSpinner()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }
    dialog.show()
  }

  private fun addKeySetBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.add_key_set_dialog, null)
    val keySetIdEd = dialogView.findViewById<EditText>(R.id.keySetIdEd)
    val keySecurityPolicySp = dialogView.findViewById<Spinner>(R.id.keySecurityPolicySp)
    keySecurityPolicySp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        GroupKeySecurityPolicy.values()
      )
    val validityTimeEd = dialogView.findViewById<EditText>(R.id.validityTimeEd)
    val epochKeyEd = dialogView.findViewById<EditText>(R.id.epochKeyEd)

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.addKeySetDialogBtn).setOnClickListener {
      val ret =
        deviceController.addKeySet(
          keySetIdEd.text.toString().toUInt().toInt(),
          GroupKeySecurityPolicy.valueOf(keySecurityPolicySp.selectedItem.toString()),
          validityTimeEd.text.toString().toULong().toLong(),
          hexStringToByteArray(epochKeyEd.text.toString())
        )
      showMessage("addKeySet : $ret")
      updateGroupSettingView()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }
    dialog.show()
  }

  private fun removeKeySetBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.remove_key_set_dialog, null)

    val keySetList = deviceController.keySetIds

    val keySetListSp = dialogView.findViewById<Spinner>(R.id.keySetListSp)
    keySetListSp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        keySetList.map { it.toString() }
      )

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.removeGroupDialogBtn).setOnClickListener {
      val selectedKeySetId = keySetListSp.selectedItem.toString().toInt()
      val ret = deviceController.removeKeySet(selectedKeySetId)
      showMessage("removeKeySet : $selectedKeySetId - $ret")
      updateGroupSettingView()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }
    dialog.show()
  }

  private fun bindKeySetBtnClick(isBind: Boolean) {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.bind_key_set_dialog, null)

    val groupList = deviceController.availableGroupIds
    val keySetList = deviceController.keySetIds

    val groupSp = dialogView.findViewById<Spinner>(R.id.groupSp)
    groupSp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        groupList.map { it.toString() }
      )

    val keySetSp = dialogView.findViewById<Spinner>(R.id.keySetSp)
    keySetSp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        keySetList.map { it.toString() }
      )

    dialogView.findViewById<Button>(R.id.bindKeySetDialogBtn).visibility =
      if (isBind) {
        View.VISIBLE
      } else {
        View.GONE
      }
    dialogView.findViewById<Button>(R.id.unbindKeySetDialogBtn).visibility =
      if (!isBind) {
        View.VISIBLE
      } else {
        View.GONE
      }

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.bindKeySetDialogBtn).setOnClickListener {
      val groupId = groupSp.selectedItem.toString().toUInt().toInt()
      val keySetId = keySetSp.selectedItem.toString().toUInt().toInt()
      val ret = deviceController.bindKeySet(groupId, keySetId)
      showMessage("bindKeySet : $groupId, $keySetId - $ret")
      updateGroupSettingView()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }

    dialogView.findViewById<Button>(R.id.unbindKeySetDialogBtn).setOnClickListener {
      val groupId = groupSp.selectedItem.toString().toUInt().toInt()
      val keySetId = keySetSp.selectedItem.toString().toUInt().toInt()
      val ret = deviceController.unbindKeySet(groupId, keySetId)
      showMessage("unbindKeySet : $groupId, $keySetId - $ret")
      updateGroupSettingView()
      requireActivity().runOnUiThread { dialog.dismiss() }
    }
    dialog.show()
  }

  private fun sendKeySetWriteBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.send_key_set_dialog, null)
    val keySetIdEd = dialogView.findViewById<EditText>(R.id.keySetIdEd)
    val keySecurityPolicySp = dialogView.findViewById<Spinner>(R.id.keySecurityPolicySp)
    keySecurityPolicySp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        GroupKeySecurityPolicy.values()
      )
    val epochKey0Ed = dialogView.findViewById<EditText>(R.id.epochKey0Ed)
    val epochStartTime0Ed = dialogView.findViewById<EditText>(R.id.epochStartTime0Ed)
    val epochKey1Ed = dialogView.findViewById<EditText>(R.id.epochKey1Ed)
    val epochStartTime1Ed = dialogView.findViewById<EditText>(R.id.epochStartTime1Ed)
    val epochKey2Ed = dialogView.findViewById<EditText>(R.id.epochKey2Ed)
    val epochStartTime2Ed = dialogView.findViewById<EditText>(R.id.epochStartTime2Ed)

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.addKeySetDialogBtn).setOnClickListener {
      scope.launch {
        val keySetWritestruct =
          GroupKeyManagementClusterGroupKeySetStruct(
            keySetIdEd.text.toString().toUInt().toInt(),
            GroupKeySecurityPolicy.valueOf(keySecurityPolicySp.selectedItem.toString())
              .id
              .toUInt()
              .toInt(),
            hexStringToByteArray(epochKey0Ed.text.toString()),
            epochStartTime0Ed.text.toString().toULong().toLong(),
            hexStringToByteArray(epochKey1Ed.text.toString()),
            epochStartTime1Ed.text.toString().toULong().toLong(),
            hexStringToByteArray(epochKey2Ed.text.toString()),
            epochStartTime2Ed.text.toString().toULong().toLong()
          )
        sendKeySetWrite(keySetWritestruct)
        requireActivity().runOnUiThread { dialog.dismiss() }
      }
    }
    dialog.show()
  }

  private suspend fun sendKeySetWrite(
    groupKeySetStruct: GroupKeyManagementClusterGroupKeySetStruct
  ) {
    val devicePtr =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }
    val cluster = ChipClusters.GroupKeyManagementCluster(devicePtr, 0)

    cluster.keySetWrite(
      object : ChipClusters.DefaultClusterCallback {
        override fun onError(e: Exception?) {
          Log.d(TAG, "onError : ", e)
          showMessage("onError : ${e.toString()}")
        }

        override fun onSuccess() {
          Log.d(TAG, "onResponse")
          showMessage("onResponse")
        }
      },
      groupKeySetStruct
    )
  }

  private fun writeGroupKeyMapBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.write_group_key_dialog, null)
    val groupIdEd = dialogView.findViewById<EditText>(R.id.groupIdEd)
    val groupKeySetIdEd = dialogView.findViewById<EditText>(R.id.groupKeySetIdEd)

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.writeGroupKeyMapBtn).setOnClickListener {
      scope.launch {
        writeGroupKeyMap(
          groupIdEd.text.toString().toUInt(),
          groupKeySetIdEd.text.toString().toUInt()
        )
        requireActivity().runOnUiThread { dialog.dismiss() }
      }
    }
    dialog.show()
  }

  private suspend fun writeGroupKeyMap(groupId: UInt, groupKeySetId: UInt) {
    val devicePtr =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }
    val cluster = ChipClusters.GroupKeyManagementCluster(devicePtr, 0)
    cluster.writeGroupKeyMapAttribute(
      object : ChipClusters.DefaultClusterCallback {
        override fun onError(e: Exception?) {
          Log.d(TAG, "onError : ", e)
          showMessage("Error : ${e.toString()}")
        }

        override fun onSuccess() {
          Log.d(TAG, "onResponse")
          showMessage("write Success")
        }
      },
      arrayListOf(
        ChipStructs.GroupKeyManagementClusterGroupKeyMapStruct(
          groupId.toInt(),
          groupKeySetId.toInt(),
          deviceController.fabricIndex
        )
      )
    )
  }

  private fun sendAddGroupBtnClick() {
    val dialogView = requireActivity().layoutInflater.inflate(R.layout.add_group_dialog, null)
    val groupIdEd = dialogView.findViewById<EditText>(R.id.groupIdEd)
    val groupNameEd = dialogView.findViewById<EditText>(R.id.groupNameEd)

    dialogView.findViewById<Button>(R.id.addGroupDialogBtn).visibility = View.GONE

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.sendGroupDialogBtn).setOnClickListener {
      scope.launch {
        sendAddGroup(groupIdEd.text.toString().toUInt(), groupNameEd.text.toString())
        requireActivity().runOnUiThread { dialog.dismiss() }
      }
    }
    dialog.show()
  }

  private suspend fun sendAddGroup(groupId: UInt, groupName: String) {
    val devicePtr =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }
    val cluster = ChipClusters.GroupsCluster(devicePtr, 0)

    cluster.addGroup(
      object : ChipClusters.GroupsCluster.AddGroupResponseCallback {
        override fun onError(e: Exception?) {
          Log.d(TAG, "onError : ", e)
          showMessage("Error : ${e.toString()}")
        }

        override fun onSuccess(status: Int?, groupID: Int?) {
          Log.d(TAG, "onResponse")
          showMessage("onResponse : $status, $groupID")
        }
      },
      groupId.toInt(),
      groupName
    )
  }

  private suspend fun readAccessControl() {
    val devicePtr =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }
    val cluster = ChipClusters.AccessControlCluster(devicePtr, 0)
    cluster.readAclAttribute(
      object : ChipClusters.AccessControlCluster.AclAttributeCallback {
        override fun onError(e: Exception?) {
          Log.d(TAG, "onError : ", e)
          showMessage("Error : $e")
        }

        override fun onSuccess(value: MutableList<AccessControlClusterAccessControlEntryStruct>?) {
          requireActivity().runOnUiThread { showAddAccessControlDialog(value) }
        }
      }
    )
  }

  private fun showAddAccessControlDialog(
    value: List<AccessControlClusterAccessControlEntryStruct>?
  ) {
    if (value == null) {
      Log.d(TAG, "Access Control read fail")
      showMessage("Access Control read fail")
      return
    }

    val dialogView =
      requireActivity().layoutInflater.inflate(R.layout.add_access_control_dialog, null)
    val groupIdEd = dialogView.findViewById<EditText>(R.id.groupIdEd)
    val accessControlEntrySp = dialogView.findViewById<Spinner>(R.id.accessControlEntrySp)
    accessControlEntrySp.adapter =
      ArrayAdapter(
        requireContext(),
        android.R.layout.simple_spinner_dropdown_item,
        AccessControlEntry.values()
      )

    val dialog = AlertDialog.Builder(requireContext()).apply { setView(dialogView) }.create()
    dialogView.findViewById<Button>(R.id.addAccessControlBtn).setOnClickListener {
      scope.launch {
        sendAccessControl(
          value,
          groupIdEd.text.toString().toUInt(),
          AccessControlEntry.valueOf(accessControlEntrySp.selectedItem.toString()).id
        )
        requireActivity().runOnUiThread { dialog.dismiss() }
      }
    }
    dialog.show()
  }

  private suspend fun sendAccessControl(
    value: List<AccessControlClusterAccessControlEntryStruct>,
    groupId: UInt,
    privilege: UInt
  ) {
    val devicePtr =
      try {
        ChipClient.getConnectedDevicePointer(requireContext(), addressUpdateFragment.deviceId)
      } catch (e: IllegalStateException) {
        Log.d(TAG, "getConnectedDevicePointer exception", e)
        showMessage("Get DevicePointer fail!")
        return
      }
    // If GroupID is already added to AccessControl, do not add it.
    val cluster = ChipClusters.AccessControlCluster(devicePtr, 0)
    val sendEntry = ArrayList<AccessControlClusterAccessControlEntryStruct>()
    for (entry in value) {
      if (
        entry.authMode == AccessControlEntry.Operate.id.toInt() /* Group */ &&
          entry.subjects != null &&
          entry.subjects!!.contains(groupId.toULong().toLong())
      ) {
        continue
      }
      sendEntry.add(entry)
    }

    val newEntry =
      AccessControlClusterAccessControlEntryStruct(
        privilege.toInt(),
        AccessControlEntry.Operate.id.toInt() /* Group */,
        arrayListOf(groupId.toULong().toLong()),
        null,
        deviceController.fabricIndex.toUInt().toInt()
      )
    sendEntry.add(newEntry)

    cluster.writeAclAttribute(
      object : ChipClusters.DefaultClusterCallback {
        override fun onError(e: Exception?) {
          Log.d(TAG, "onError : ", e)
          showMessage("Error : ${e.toString()}")
        }

        override fun onSuccess() {
          Log.d(TAG, "onResponse")
          showMessage("write Success")
        }
      },
      sendEntry
    )
  }

  override fun onStart() {
    super.onStart()

    updateGroupSettingView()
  }

  private fun updateGroupSettingView() {
    requireActivity().runOnUiThread {
      var viewString = "Group :\n"

      for (groupId in deviceController.availableGroupIds) {
        val keySetIdString =
          if (deviceController.findKeySetId(groupId).isPresent) {
            deviceController.findKeySetId(groupId).get().toString()
          } else {
            "[]"
          }
        viewString += "\t$groupId, ${deviceController.getGroupName(groupId)}, $keySetIdString\n"
      }

      viewString += "\nKeySet :\n"
      for (keySetId in deviceController.keySetIds) {
        viewString +=
          "\t$keySetId, ${deviceController.getKeySecurityPolicy(keySetId).map { it.name }}\n"
      }

      binding.multiAdminClusterCommandStatus.text = viewString
    }
  }

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

  inner class ChipControllerCallback : GenericChipDeviceListener() {
    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 showMessage(msg: String) {
    requireActivity().runOnUiThread { binding.groupSettingStatusTv.text = msg }
  }

  companion object {
    private const val TAG = "GroupSettingFragment"

    fun newInstance(): GroupSettingFragment = GroupSettingFragment()

    private const val HEX_RADIX = 16
    private const val HEX_BIT_SHIFT = 4

    private fun hexStringToByteArray(hexString: String): ByteArray {
      val len = hexString.length
      val data = ByteArray(len / 2)
      var i = 0
      while (i < len) {
        data[i / 2] =
          ((Character.digit(hexString[i], HEX_RADIX) shl HEX_BIT_SHIFT) +
              Character.digit(hexString[i + 1], HEX_RADIX))
            .toByte()
        i += 2
      }
      return data
    }

    enum class AccessControlEntry(val id: UInt) {
      Manage(4U),
      Operate(3U),
      ProxyView(2U),
      View(1U),
      Administer(5U)
    }
  }
}
