import 'package:aves/model/activity/activity_entry.dart'; import 'package:aves/model/activity/activity_track.dart'; import 'package:latlong2/latlong.dart' show Distance, LengthUnit; class ActivityFormatters { static final Distance _distance = Distance(); static String distance(double? meters) { if (meters == null) return '-'; return '${(meters / 1000).toStringAsFixed(2)} km'; } static String distanceDelta(double? computed, double? file) { if (computed == null || file == null) return '-'; final delta = computed - file; final sign = delta >= 0 ? '+' : ''; return '$sign${(delta / 1000).toStringAsFixed(2)} km'; } static String elevation(double? meters) { if (meters == null) return '-'; return '${meters.round()} m'; } static String entryElevation(double? meters) { if (meters == null) return 'D+ -'; return 'D+ ${meters.round()} m'; } static String elevationDelta(double? computed, double? file) { if (computed == null || file == null) return '-'; final delta = computed - file; final sign = delta >= 0 ? '+' : ''; return '$sign${delta.round()} m'; } static String entryDate(ActivityEntry entry) { final millis = entry.startTimeMillis; if (millis == null) return 'Data -'; final date = DateTime.fromMillisecondsSinceEpoch(millis).toLocal(); final day = date.day.toString().padLeft(2, '0'); final month = date.month.toString().padLeft(2, '0'); final year = date.year.toString().padLeft(4, '0'); final hour = date.hour.toString().padLeft(2, '0'); final minute = date.minute.toString().padLeft(2, '0'); return '$day/$month/$year $hour:$minute'; } static String entryDuration(int? millis) { if (millis == null) return '-'; final duration = Duration(milliseconds: millis); final hours = duration.inHours; final minutes = duration.inMinutes.remainder(60); final seconds = duration.inSeconds.remainder(60); if (hours > 0) { return '${hours}h ${minutes}m'; } if (minutes > 0) { return '${minutes}m ${seconds}s'; } return '${seconds}s'; } static double? computeDistanceFromTrack(ActivityTrack activity) { final points = activity.validPoints; if (points.length < 2) return null; double total = 0; for (int i = 1; i < points.length; i++) { final segment = _distance.as( LengthUnit.Meter, points[i - 1], points[i], ); if (!segment.isFinite || segment <= 0) continue; if (segment > 500) continue; total += segment; } return total > 0 ? total : null; } static double? readDiagnosticDouble(String? diagnostics, String key) { if (diagnostics == null || diagnostics.isEmpty) return null; for (final line in diagnostics.split('\n')) { final index = line.indexOf('='); if (index <= 0) continue; final currentKey = line.substring(0, index).trim(); if (currentKey != key) continue; final value = line.substring(index + 1).trim(); if (value == 'null' || value.isEmpty) return null; return double.tryParse(value.replaceAll(',', '.')); } return null; } static String normalizePath(String path) { final trimmed = path.trim(); return trimmed.endsWith('/') ? trimmed : '$trimmed/'; } static bool isExpectedActivityRoot( String? selectedPath, String expectedPath, ) { if (selectedPath == null || selectedPath.trim().isEmpty) { return false; } return normalizePath(selectedPath) == normalizePath(expectedPath); } }