B4A=true
Group=Default Group
ModulesStructureVersion=1
Type=Service
Version=9.9
@EndOfDesignText@
#Region Service Attributes
    #StartAtBoot: True
    #ExcludeFromLibrary: True
#End Region

' TrackingService - Persistent background service for GPS updates
Sub Process_Globals
	Private GPS1 As GPS
	Private TrackingTimer As Timer
	Public IsTracking As Boolean = False
	Private LastUpdateTimestamp As Long = 0
	Private MinUpdateInterval As Long = 10000 ' 10 seconds
	Private LastLat, LastLon As Double
	Private pw As PhoneWakeState
End Sub

Sub Service_Create
	GPS1.Initialize("GPS")
	TrackingTimer.Initialize("TrackingTimer", 15000) ' 15 seconds
End Sub

Sub Service_Start (StartingIntent As Intent)
	' On Android 8+, Service.StartForeground MUST be called immediately.
	Service.StartForeground(1, CreateNotification("Bus Tracking Active", "Updating location in real-time..."))
End Sub

Sub Service_Destroy
	StopTracking
End Sub

Public Sub StartTracking
	Try
		If Not(GPS1.GPSEnabled) Then
			ToastMessageShow("Please enable GPS on your device", True)
			Return
		End If
	    
		' Keep CPU alive in background
		pw.PartialLock
		
		GPS1.Start(0, 0)
		TrackingTimer.Enabled = True
		IsTracking = True
		Log("Tracking started successfully")
	Catch
		Log("Error in StartTracking: " & LastException)
		ToastMessageShow("Error starting GPS", True)
		IsTracking = False
	End Try
End Sub

Public Sub StopTracking
	GPS1.Stop
	TrackingTimer.Enabled = False
	IsTracking = False
	pw.ReleaseKeepAlive ' Corrected B4A method
	Log("Tracking stopped")
End Sub

Sub GPS_LocationChanged (Location1 As Location)
	LastLat = Location1.Latitude
	LastLon = Location1.Longitude
	
	If IsTracking Then
		SendLocation(LastLat, LastLon)
	End If
End Sub

Sub TrackingTimer_Tick
	If Not(IsTracking) Then Return
    
	' If we haven't updated in a while (bus stationary), send heartbeat
	Log("Tracking heartbeat check...")
	If LastLat <> 0 And LastLon <> 0 Then
		SendLocation(LastLat, LastLon)
	End If
End Sub

Sub SendLocation(lat As Double, lon As Double)
	' Throttling check
	Dim now As Long = DateTime.Now
	If now < LastUpdateTimestamp + MinUpdateInterval Then
		Return
	End If
	
	LastUpdateTimestamp = now
	Dim batt As Int = GetBatteryLevel
	
	Log("Sending update: " & lat & ", " & lon & " (Batt: " & batt & "%)")
	
	Dim data As Map
	data.Initialize
	data.Put("latitude", lat)
	data.Put("longitude", lon)
	data.Put("battery_level", GetBatteryLevel)
    
	Dim json As JSONGenerator
	json.Initialize(data)
    
	Dim job As HttpJob
	job.Initialize("status", Me)
	job.PostString(APIModule.ServerURL & "/status.php", json.ToString)
	
	' Handle timeout and headers
	APIModule.SetAuthHeader(job, APIModule.GetToken)
	Try
		' Set explicit 30s timeout for mobile networks
		Dim jo As JavaObject = job.GetRequest
		jo.RunMethod("setTimeout", Array(30000))
	Catch
		Log("Error setting timeout: " & LastException)
	End Try
End Sub

Sub JobDone(Job As HttpJob)
	If Job.Success Then
		Log("Server received update successfully")
		' Handle remote commands if server sends any in JSON
		Try
			Dim parser As JSONParser
			parser.Initialize(Job.GetString)
			Dim root As Map = parser.NextObject
			Dim sStatus As String = root.GetDefault("tracking_status", "active")
			If sStatus = "stop" Then
				Log("Remote stop command received")
				StopTracking
			End If
		Catch
			Log("Error parsing server response: " & LastException)
		End Try
	Else
		Log("Update failed: " & Job.ErrorMessage)
	End If
	Job.Release
End Sub

' ================= UTILITIES =================

Sub GetBatteryLevel As Int
	Try
		Dim jo As JavaObject
		jo.InitializeContext
		Dim filter As JavaObject
		filter.InitializeNewInstance("android.content.IntentFilter", Array("android.intent.action.BATTERY_CHANGED"))
		Dim intent1 As Intent = jo.RunMethod("registerReceiver", Array(Null, filter))
		Dim level As Int = intent1.GetExtra("level")
		Dim scale As Int = intent1.GetExtra("scale")
		Return (level / scale) * 100
	Catch
		Log("Error getting battery level: " & LastException)
		Return 100
	End Try
End Sub

Sub CreateNotification(title As String, body As String) As Notification
	Dim n As Notification
	' Initialize2 is modern B4A way, automatically creates channel with importance
	' Level 3 = Default level
	n.Initialize2(3)
	n.Icon = "icon"
	n.SetInfo(title, body, Main)
	' On Android 13+, the app might need POST_NOTIFICATIONS permission to show this.
	Return n
End Sub

' CreateNotificationChannel not needed when using Initialize2
