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.AdapterView
import android.widget.ArrayAdapter
import android.widget.Toast
import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope
import chip.devicecontroller.ChipClusters
import com.google.chip.chiptool.ChipClient
import com.google.chip.chiptool.R
import com.google.chip.chiptool.databinding.AttestationTestFragmentBinding
import com.google.chip.chiptool.databinding.SensorClientFragmentBinding
import com.google.chip.chiptool.util.DeviceIdUtil
import com.jjoe64.graphview.LabelFormatter
import com.jjoe64.graphview.Viewport
import com.jjoe64.graphview.series.DataPoint
import com.jjoe64.graphview.series.LineGraphSeries
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

private typealias ReadCallback = ChipClusters.IntegerAttributeCallback
private typealias TemperatureReadCallback =
    ChipClusters.TemperatureMeasurementCluster.MeasuredValueAttributeCallback

private typealias PressureReadCallback =
    ChipClusters.PressureMeasurementCluster.MeasuredValueAttributeCallback

private typealias RelativeHumidityReadCallback =
    ChipClusters.RelativeHumidityMeasurementCluster.MeasuredValueAttributeCallback

class SensorClientFragment : Fragment() {
  private lateinit var scope: CoroutineScope

  // History of sensor values
  private val sensorData = LineGraphSeries<DataPoint>()

  // Device whose attribute is subscribed
  private var subscribedDevicePtr = 0L

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

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

    return binding.root
  }

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)

    ChipClient.getDeviceController(requireContext()).setCompletionListener(null)
    binding.deviceIdEd.setOnEditorActionListener { textView, actionId, _ ->
      if (actionId == EditorInfo.IME_ACTION_DONE) {
        resetSensorGraph() // reset the graph on device change
      }
      actionId == EditorInfo.IME_ACTION_DONE
    }

    binding.endpointIdEd.setOnEditorActionListener { textView, actionId, _ ->
      if (actionId == EditorInfo.IME_ACTION_DONE)
        resetSensorGraph() // reset the graph on endpoint change
      actionId == EditorInfo.IME_ACTION_DONE
    }

    binding.clusterNameSpinner.adapter = makeClusterNamesAdapter()
    binding.clusterNameSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener {
      override fun onNothingSelected(parent: AdapterView<*>?) = Unit
      override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) {
        resetSensorGraph() // reset the graph on cluster change
      }
    }

    binding.readSensorBtn.setOnClickListener { scope.launch { readSensorCluster() } }
    binding.watchSensorBtn.setOnCheckedChangeListener { _, isChecked ->
      if (isChecked) {
        scope.launch { subscribeSensorCluster() }
      } else {
        unsubscribeSensorCluster()
      }
    }

    val currentTime = Calendar.getInstance().time.time
    binding.sensorGraph.addSeries(sensorData)
    binding.sensorGraph.viewport.isXAxisBoundsManual = true
    binding.sensorGraph.viewport.setMinX(currentTime.toDouble())
    binding.sensorGraph.viewport.setMaxX(currentTime.toDouble() + MIN_REFRESH_PERIOD_S * 1000 * MAX_DATA_POINTS)
    binding.sensorGraph.gridLabelRenderer.padding = 30
    binding.sensorGraph.gridLabelRenderer.numHorizontalLabels = 4
    binding.sensorGraph.gridLabelRenderer.setHorizontalLabelsAngle(150)
    binding.sensorGraph.gridLabelRenderer.labelFormatter = object : LabelFormatter {
      override fun setViewport(viewport: Viewport?) = Unit
      override fun formatLabel(value: Double, isValueX: Boolean): String {
        if (isValueX)
          return SimpleDateFormat("H:mm:ss").format(Date(value.toLong())).toString()
        if (value >= 100.0)
          return "%.1f".format(value)
        return "%.2f".format(value)
      }
    }
  }

  override fun onStart() {
    super.onStart()
    binding.deviceIdEd.setText(DeviceIdUtil.getLastDeviceId(requireContext()).toString())
  }

  override fun onStop() {
    resetSensorGraph() // reset the graph on fragment exit
    super.onStop()
  }

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

  private fun resetSensorGraph() {
    binding.watchSensorBtn.isChecked = false
    binding.sensorGraph.visibility = View.INVISIBLE
    sensorData.resetData(emptyArray())
  }

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

  private suspend fun readSensorCluster() {
    try {
      val deviceId = binding.deviceIdEd.text.toString().toULong().toLong()
      val endpointId = binding.endpointIdEd.text.toString().toInt()
      val clusterName = binding.clusterNameSpinner.selectedItem.toString()
      val clusterRead = CLUSTERS[clusterName]!!["read"] as (Long, Int, ReadCallback) -> Unit
      val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId)
      val callback = makeReadCallback(clusterName, false)

      clusterRead(device, endpointId, callback)
    } catch (ex: Exception) {
      showMessage(R.string.sensor_client_read_error_text, ex.toString())
    }
  }

  private suspend fun subscribeSensorCluster() {
    try {
      val deviceId = binding.deviceIdEd.text.toString().toULong().toLong()
      val endpointId = binding.endpointIdEd.text.toString().toInt()
      val clusterName = binding.clusterNameSpinner.selectedItem.toString()
      val clusterSubscribe = CLUSTERS[clusterName]!!["subscribe"] as (Long, Int, ReadCallback) -> Unit
      val device = ChipClient.getConnectedDevicePointer(requireContext(), deviceId)
      val callback = makeReadCallback(clusterName, true)

      clusterSubscribe(device, endpointId, callback)
      subscribedDevicePtr = device
    } catch (ex: Exception) {
      showMessage(R.string.sensor_client_subscribe_error_text, ex.toString())
    }
  }

  private fun unsubscribeSensorCluster() {
    if (subscribedDevicePtr == 0L)
      return

    try {
      ChipClient.getDeviceController(requireContext()).shutdownSubscriptions()
      subscribedDevicePtr = 0
    } catch (ex: Exception) {
      showMessage(R.string.sensor_client_unsubscribe_error_text, ex.toString())
    }
  }

  private fun makeReadCallback(clusterName: String, addToGraph: Boolean): ReadCallback {
    return object : ReadCallback {
      val clusterConfig = CLUSTERS[clusterName]!!

      override fun onSuccess(value: Int) {
        val unitValue = clusterConfig["unitValue"] as Double
        val unitSymbol = clusterConfig["unitSymbol"] as String
        consumeSensorValue(value * unitValue, unitSymbol, addToGraph)
      }

      override fun onError(ex: Exception) {
        showMessage(R.string.sensor_client_read_error_text, ex.toString())
      }
    }
  }

  private fun consumeSensorValue(value: Double, unitSymbol: String, addToGraph: Boolean) {
    requireActivity().runOnUiThread {
      binding.lastValueTv.text = requireContext().getString(
          R.string.sensor_client_last_value_text, value, unitSymbol
      )

      if (addToGraph) {
        val isFirstSample = sensorData.isEmpty
        val dataPoint = DataPoint(Calendar.getInstance().time, value)
        sensorData.appendData(dataPoint, true, MAX_DATA_POINTS)
        if (isFirstSample) {
          // Make the graph visible on the first sample. Also, workaround a bug in graphview
          // related to calculating the viewport when there is only one data point by
          // duplicating the first sample.
          sensorData.appendData(dataPoint, true, MAX_DATA_POINTS)
          binding.sensorGraph.visibility = View.VISIBLE
        }
      }
    }
  }

  private fun showMessage(msgResId: Int, stringArgs: String? = null) {
    requireActivity().runOnUiThread {
      val context = requireContext()
      val message = context.getString(msgResId, stringArgs)
      Toast.makeText(context, message, Toast.LENGTH_SHORT).show()
      Log.i(TAG, message)
    }
  }

  companion object {
    private const val TAG = "SensorClientFragment"
    private const val MIN_REFRESH_PERIOD_S = 2
    private const val MAX_REFRESH_PERIOD_S = 10
    private const val MAX_DATA_POINTS = 60
    private val CLUSTERS = mapOf(
        "Temperature" to mapOf(
            "read" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.TemperatureMeasurementCluster(device, endpointId)
              cluster.readMeasuredValueAttribute(makeTemperatureReadCallback(callback))
            },
            "subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.TemperatureMeasurementCluster(device, endpointId)
              cluster.subscribeMeasuredValueAttribute(makeTemperatureReadCallback(callback),
                  MIN_REFRESH_PERIOD_S,
                  MAX_REFRESH_PERIOD_S)
            },
            "unitValue" to 0.01,
            "unitSymbol" to "\u00B0C"
        ),
        "Pressure" to mapOf(
            "read" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.PressureMeasurementCluster(device, endpointId)
              cluster.readMeasuredValueAttribute(makePressureReadCallback(callback))
            },
            "subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.PressureMeasurementCluster(device, endpointId)
              cluster.subscribeMeasuredValueAttribute(makePressureReadCallback(callback),
                  MIN_REFRESH_PERIOD_S,
                  MAX_REFRESH_PERIOD_S)
            },
            "unitValue" to 1.0,
            "unitSymbol" to "hPa"
        ),
        "Relative Humidity" to mapOf(
            "read" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.RelativeHumidityMeasurementCluster(device, endpointId)
              cluster.readMeasuredValueAttribute(makeHumidityReadCallback(callback))
            },
            "subscribe" to { device: Long, endpointId: Int, callback: ReadCallback ->
              val cluster = ChipClusters.RelativeHumidityMeasurementCluster(device, endpointId)
              cluster.subscribeMeasuredValueAttribute(makeHumidityReadCallback(callback),
                  MIN_REFRESH_PERIOD_S,
                  MAX_REFRESH_PERIOD_S)
            },
            "unitValue" to 0.01,
            "unitSymbol" to "%"
        )
    )

    private fun makeTemperatureReadCallback(callback: ReadCallback): TemperatureReadCallback {
      return object : TemperatureReadCallback {
        override fun onSuccess(value: Int?) {
          value?.let { callback.onSuccess(it) }
        }

        override fun onError(error: java.lang.Exception?) {
          callback.onError(error)
        }
      }
    }

    private fun makePressureReadCallback(callback: ReadCallback): PressureReadCallback {
      return object : PressureReadCallback {
        override fun onSuccess(value: Int?) {
          value?.let { callback.onSuccess(it) }
        }

        override fun onError(error: java.lang.Exception?) {
          callback.onError(error)
        }
      }
    }

    private fun makeHumidityReadCallback(callback: ReadCallback): RelativeHumidityReadCallback {
      return object : RelativeHumidityReadCallback {
        override fun onSuccess(value: Int?) {
          value?.let { callback.onSuccess(it) }
        }

        override fun onError(error: java.lang.Exception?) {
          callback.onError(error)
        }
      }
    }

    fun newInstance(): SensorClientFragment = SensorClientFragment()
  }
}
