package mx.trackermap.TrackerMap.android.map import android.content.Intent import android.os.Bundle import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import androidx.core.text.HtmlCompat import androidx.fragment.app.Fragment import androidx.fragment.app.viewModels import kotlin.time.ExperimentalTime import kotlinx.coroutines.DelicateCoroutinesApi import mx.trackermap.TrackerMap.android.R import mx.trackermap.TrackerMap.android.databinding.UnitMapFragmentBinding import mx.trackermap.TrackerMap.android.details.DetailsActivity import mx.trackermap.TrackerMap.android.shared.MarkerTransformations import mx.trackermap.TrackerMap.android.shared.UnitRenderData import mx.trackermap.TrackerMap.android.units.UnitsViewModel import mx.trackermap.TrackerMap.client.models.MapLayer import mx.trackermap.TrackerMap.client.models.UnitInformation @DelicateCoroutinesApi @ExperimentalTime class UnitMapFragment : Fragment() { private val unitsViewModel: UnitsViewModel by viewModels( ownerProducer = { requireActivity() } ) private var _binding: UnitMapFragmentBinding? = null private val binding get() = _binding!! private lateinit var unitsMapFragment: MapFragment private var shouldCenter = true override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View { _binding = UnitMapFragmentBinding.inflate(inflater) return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) initializeMap() } override fun onResume() { super.onResume() setupObservers() } override fun onPause() { super.onPause() removeObservers() } private fun initializeMap() { shouldCenter = true unitsMapFragment = childFragmentManager.findFragmentById(R.id.unitsMap) as MapFragment unitsMapFragment.markerCallback = unitsViewModel::selectUnitWith val layer = MapLayer.defaultLayer binding.attributionText.text = HtmlCompat.fromHtml(layer.attribution, 0) } private fun setupObservers() { Log.d("UnitMapFragment", "setupObservers()") unitsViewModel.units.observe(viewLifecycleOwner) { units -> Log.d("UnitMapFragment", "Available units: $units") unitsMapFragment.display( units.mapNotNull(MarkerTransformations::unitToMarker).toTypedArray(), isReport = false, center = shouldCenter ) if (units.isNotEmpty()) { shouldCenter = false } } unitsViewModel.selectedUnit.observe(viewLifecycleOwner) { selectedUnit -> Log.d("UnitMapFragment", "Selected Unit: $selectedUnit") binding.mapUnitCard.visibility = if (selectedUnit == null) View.GONE else View.VISIBLE selectedUnit?.let { unit -> if (unit.position == null || unit.position!!.latitude == null || unit.position!!.longitude == null) { return@let } UnitRenderData.render( UnitRenderData.UnitRenderViewHolder( unitName = binding.unitName, statusIcon = binding.statusIcon, engineStopIcon = binding.engineStopIcon, gridLayout = binding.gridLayout, detailsButton = binding.detailsButton, reportsButton = binding.reportsButton, commandsButton = binding.commandsButton ), binding.mapUnitCard.context, unit, this::itemAction ) unitsMapFragment.focusOn(unit.position!!.latitude!!, unit.position!!.longitude!!) } } unitsViewModel.mapLayerType.observe(viewLifecycleOwner) { type -> Log.d("UnitMapFragment", "Loading layer!") unitsMapFragment.updateLayer(type) unitsViewModel.selectedUnit.value?.let { unitsMapFragment.focusOn(it.position!!.latitude!!, it.position!!.longitude!!) } val layer = MapLayer.layers[type]!! binding.attributionText.text = HtmlCompat.fromHtml(layer.attribution, 0) } unitsViewModel.geofences.observe(viewLifecycleOwner) { geofences -> unitsMapFragment.displayGeofences(geofences.values.toTypedArray()) } } private fun removeObservers() { Log.d("UnitMapFragment", "removeObservers()") unitsViewModel.units.removeObservers(viewLifecycleOwner) unitsViewModel.selectedUnit.removeObservers(viewLifecycleOwner) unitsViewModel.mapLayerType.removeObservers(viewLifecycleOwner) unitsViewModel.geofences.removeObservers(viewLifecycleOwner) } private fun itemAction(unit: UnitInformation, action: UnitRenderData.Action) { when (action) { UnitRenderData.Action.DETAILS, UnitRenderData.Action.REPORTS, UnitRenderData.Action.COMMANDS -> { Log.d("UnitMapFragment", "Action: $action - Unit: $unit") val activity = requireActivity() val intent = Intent(activity.applicationContext, DetailsActivity::class.java) intent.putExtra(DetailsActivity.DEVICE_ID_EXTRA, unit.device.id) intent.putExtra(DetailsActivity.DEVICE_NAME_EXTRA, unit.device.name) intent.putExtra(DetailsActivity.DEVICE_CATEGORY_EXTRA, unit.device.category) intent.putExtra(DetailsActivity.ACTION_EXTRA, action) startActivity(intent) } UnitRenderData.Action.CLICK -> { unitsViewModel.selectUnit(unit) } } } }