import 'package:flutter/material.dart'; enum AppMapType { openStreetMap, googleMaps } class AppLatLng { final double latitude; final double longitude; const AppLatLng(this.latitude, this.longitude); @override bool operator ==(Object other) => identical(this, other) || other is AppLatLng && runtimeType == other.runtimeType && latitude == other.latitude && longitude == other.longitude; @override int get hashCode => latitude.hashCode ^ longitude.hashCode; } class AppMapMarker { final String id; final AppLatLng position; final Widget? iconWidget; final double heading; // degrees (0-360) final String? label; final VoidCallback? onTap; const AppMapMarker({ required this.id, required this.position, this.iconWidget, this.heading = 0.0, this.label, this.onTap, }); } class AppPolyline { final String id; final List points; final Color color; final double width; const AppPolyline({ required this.id, required this.points, this.color = Colors.cyanAccent, this.width = 4.0, }); } class MapConfig { final String tileUrlTemplate; final String attributionText; final String userAgent; final double minZoom; final double maxZoom; final List subdomains; const MapConfig({ this.tileUrlTemplate = 'https://tile.openstreetmap.org/{z}/{x}/{y}.png', this.attributionText = '© OpenStreetMap contributors', this.userAgent = 'MotorcycleDashboard/1.0 (contact: support@earnable.store)', this.minZoom = 3.0, this.maxZoom = 19.0, this.subdomains = const [], }); } abstract class AppMapProvider { AppMapType get type; String get name; Widget buildMapView({ required BuildContext context, required AppLatLng center, required double zoom, required List markers, required List polylines, required bool isFollowMode, required MapConfig config, required ValueChanged? onPositionChanged, required VoidCallback? onUserInteraction, }); }