package com.shukria.kiosklauncher.ui import android.app.ActivityManager import android.content.Context import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.ImageButton import android.widget.ProgressBar import android.widget.TextView import android.widget.Toast import androidx.cardview.widget.CardView import androidx.core.content.ContextCompat import androidx.fragment.app.Fragment import com.google.android.material.button.MaterialButton import print.Print import com.shukria.kiosklauncher.R import com.shukria.kiosklauncher.service.ScreenShareService import com.shukria.kiosklauncher.util.DeviceInfo import com.shukria.kiosklauncher.util.KioskUtil import com.shukria.kiosklauncher.util.MQTTManager import com.shukria.kiosklauncher.util.WebSocketManager class HomeFragment : Fragment() { private lateinit var imageButtonExit: ImageButton // Connection Pills private lateinit var pillMqtt: TextView private lateinit var pillWebSocket: TextView // Terminal Info private lateinit var textDeviceModel: TextView private lateinit var textSerialNumber: TextView private lateinit var textOsVersion: TextView private lateinit var textAppVersion: TextView // System Metrics private lateinit var textMemoryStatus: TextView private lateinit var progressMemory: ProgressBar private lateinit var textPrinterStatus: TextView private lateinit var btnPrinterTest: MaterialButton // Quick Actions private lateinit var cardInstalledApps: CardView private lateinit var cardMarketplace: CardView private lateinit var cardScreenShare: CardView private lateinit var textScreenShareStatus: TextView // Background update handler private val updateHandler = Handler(Looper.getMainLooper()) private val updateRunnable = object : Runnable { override fun run() { updateDiagnostics() updateHandler.postDelayed(this, 3000) // Update every 3 seconds } } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { val v = inflater.inflate(R.layout.fragment_home, container, false) // Bind views imageButtonExit = v.findViewById(R.id.imageButton_exit) pillMqtt = v.findViewById(R.id.pill_mqtt) pillWebSocket = v.findViewById(R.id.pill_websocket) textDeviceModel = v.findViewById(R.id.text_device_model) textSerialNumber = v.findViewById(R.id.text_serial_number) textOsVersion = v.findViewById(R.id.text_os_version) textAppVersion = v.findViewById(R.id.text_app_version) textMemoryStatus = v.findViewById(R.id.text_memory_status) progressMemory = v.findViewById(R.id.progress_memory) textPrinterStatus = v.findViewById(R.id.text_printer_status) btnPrinterTest = v.findViewById(R.id.btn_printer_test) cardInstalledApps = v.findViewById(R.id.card_installed_apps) cardMarketplace = v.findViewById(R.id.card_marketplace) cardScreenShare = v.findViewById(R.id.card_screen_share) textScreenShareStatus = v.findViewById(R.id.text_screenshare_status) // Initialize static terminal info initializeTerminalInfo() // Set up click listeners setupClickListeners() return v } private fun initializeTerminalInfo() { textDeviceModel.text = Build.MODEL ?: "Unknown" textSerialNumber.text = DeviceInfo.getSerialNumber(requireContext()) textOsVersion.text = "Android ${Build.VERSION.RELEASE}" textAppVersion.text = DeviceInfo.getAppVersion(requireContext()) } private fun setupClickListeners() { imageButtonExit.setOnClickListener { KioskUtil.stopKioskMode(requireActivity()) } cardInstalledApps.setOnClickListener { requireActivity().supportFragmentManager.beginTransaction() .replace(R.id.fragmentContainerView, AppsListFragment()) .addToBackStack(null) .commit() } cardMarketplace.setOnClickListener { requireActivity().supportFragmentManager.beginTransaction() .replace(R.id.fragmentContainerView, MarketplaceFragment.newInstance()) .addToBackStack(null) .commit() } cardScreenShare.setOnClickListener { handleScreenShareToggle() } btnPrinterTest.setOnClickListener { testPrinter() } } private fun handleScreenShareToggle() { val sn = MQTTManager.currentSerialNumber ?: run { Toast.makeText(requireContext(), "Not connected to TMS", Toast.LENGTH_SHORT).show() return } if (ScreenShareService.isRunning()) { ScreenShareService.stop(requireContext()) Toast.makeText(requireContext(), "Screen share stopped", Toast.LENGTH_SHORT).show() updateScreenShareStatus(false) } else { ScreenShareService.prepare(requireContext(), sn) ScreenCaptureActivity.start(requireContext(), sn) Toast.makeText(requireContext(), "Screen share starting…", Toast.LENGTH_SHORT).show() updateScreenShareStatus(true) } } private fun testPrinter() { try { // Print a simple self-test receipt Print.printSelf() Toast.makeText(requireContext(), "Printer test initiated", Toast.LENGTH_SHORT).show() } catch (e: Exception) { Log.e("HomeFragment", "Printer test failed", e) Toast.makeText(requireContext(), "Printer test failed: ${e.message}", Toast.LENGTH_SHORT).show() } } private fun updateDiagnostics() { // Update connection pills updateConnectionStatus() // Update memory status updateMemoryStatus() // Update printer status updatePrinterStatus() // Update screen share status updateScreenShareStatus(ScreenShareService.isRunning()) } private fun updateConnectionStatus() { // MQTT status val mqttConnected = MQTTManager.isConnected if (mqttConnected) { pillMqtt.text = "MQTT: Connected" pillMqtt.setBackgroundResource(R.drawable.bg_pill_active) } else { pillMqtt.text = "MQTT: Disconnected" pillMqtt.setBackgroundResource(R.drawable.bg_pill_inactive) } // WebSocket status val wsConnected = WebSocketManager.getInstance().webSocketClient?.isOpen == true if (wsConnected) { pillWebSocket.text = "WebSocket: Connected" pillWebSocket.setBackgroundResource(R.drawable.bg_pill_active) } else { pillWebSocket.text = "WebSocket: Disconnected" pillWebSocket.setBackgroundResource(R.drawable.bg_pill_inactive) } } private fun updateMemoryStatus() { try { val activityManager = requireContext().getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val memoryInfo = ActivityManager.MemoryInfo() activityManager.getMemoryInfo(memoryInfo) val totalMem = memoryInfo.totalMem val availMem = memoryInfo.availMem val usedMem = totalMem - availMem val totalMemMB = totalMem / (1024 * 1024) val availMemMB = availMem / (1024 * 1024) val usedMemMB = usedMem / (1024 * 1024) val usedPercentage = ((usedMem.toDouble() / totalMem.toDouble()) * 100).toInt() textMemoryStatus.text = "${usedMemMB}MB / ${totalMemMB}MB" progressMemory.progress = usedPercentage // Change color based on usage when { usedPercentage > 85 -> progressMemory.progressTintList = ContextCompat.getColorStateList(requireContext(), R.color.pill_disconnected) usedPercentage > 70 -> progressMemory.progressTintList = ContextCompat.getColorStateList(requireContext(), R.color.accent_amber) else -> progressMemory.progressTintList = ContextCompat.getColorStateList(requireContext(), R.color.accent_emerald) } } catch (e: Exception) { Log.e("HomeFragment", "Failed to get memory info", e) textMemoryStatus.text = "N/A" } } private fun updatePrinterStatus() { try { // Query real-time printer status // Status byte 2: Paper status val paperStatus = Print.GetRealTimeStatus(2.toByte()) // Status byte 4: Cover and other errors val errorStatus = Print.GetRealTimeStatus(4.toByte()) if (paperStatus != null && paperStatus.isNotEmpty()) { val status = paperStatus[0].toInt() when { (status and 0x60) != 0 -> { textPrinterStatus.text = "Paper Low" textPrinterStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.accent_amber) ) } (status and 0x0C) != 0 -> { textPrinterStatus.text = "Paper Out" textPrinterStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.pill_disconnected) ) } else -> { textPrinterStatus.text = "Ready" textPrinterStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.accent_emerald) ) } } } if (errorStatus != null && errorStatus.isNotEmpty()) { val error = errorStatus[0].toInt() if ((error and 0x20) != 0) { textPrinterStatus.text = "Cover Open" textPrinterStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.pill_disconnected) ) } } } catch (e: Exception) { Log.e("HomeFragment", "Failed to get printer status", e) textPrinterStatus.text = "Unknown" textPrinterStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.text_secondary) ) } } private fun updateScreenShareStatus(isRunning: Boolean) { if (isRunning) { textScreenShareStatus.text = "Screen sharing is active" textScreenShareStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.accent_emerald) ) cardScreenShare.setCardBackgroundColor( ContextCompat.getColor(requireContext(), R.color.card_bg_elevated) ) } else { textScreenShareStatus.text = "Tap to start screen sharing" textScreenShareStatus.setTextColor( ContextCompat.getColor(requireContext(), R.color.text_secondary) ) cardScreenShare.setCardBackgroundColor( ContextCompat.getColor(requireContext(), R.color.card_bg_elevated) ) } } override fun onStart() { super.onStart() // Start the background diagnostic updates updateHandler.post(updateRunnable) } override fun onStop() { super.onStop() // Stop the background diagnostic updates updateHandler.removeCallbacks(updateRunnable) } }