import 'package:equatable/equatable.dart'; import 'package:intaleq_maps/intaleq_maps.dart'; import '../../../data/models/route_model.dart'; import '../../../data/models/place_model.dart'; enum NavigationStatus { initial, loading, mapReady, routePreview, navigating, arrived, error, } enum MapThemeType { vectorLight, vectorDark, satellite, } class NavigationState extends Equatable { final NavigationStatus status; final LatLng? myLocation; final double altitude; // Altitude AMSL in meters (defaults to 0.0) final double heading; final double speed; final List routes; final int selectedRouteIndex; final LatLng? destination; final String destinationTitle; final String originTitle; final List> routeSteps; final int currentStepIndex; final String currentInstruction; final String nextInstruction; final double distanceToNextStep; final double remainingDistance; final double remainingDuration; final int currentManeuverModifier; final String arrivalTime; final bool isMuted; final bool isCameraLocked; final MapThemeType mapTheme; final Set markers; final Set polylines; final List searchResults; final bool isSelectingLocationOnMap; final String? activePickerMode; final LatLng? pickedLocation; final bool isOnline; final String? errorMessage; final int selectedVehicleColor; final String selectedVehicleStyle; final double vehicleScale; final List recentSearches; final bool isSearching; final bool isOrbiting; final double orbitSpeed; final bool isSunPlaying; final int sunTimeMinutes; final double terrainExaggeration; final double cameraTilt; final bool showBuildings; final bool showContours; final bool showHillshading; final bool isTouristModeEnabled; final String? selectedLandmarkId; const NavigationState({ this.status = NavigationStatus.initial, this.myLocation, this.altitude = 0.0, this.heading = 0.0, this.speed = 0.0, this.routes = const [], this.selectedRouteIndex = 0, this.destination, this.destinationTitle = '', this.originTitle = 'موقعي الحالي', this.routeSteps = const [], this.currentStepIndex = 0, this.currentInstruction = '', this.nextInstruction = '', this.distanceToNextStep = 0.0, this.remainingDistance = 0.0, this.remainingDuration = 0.0, this.currentManeuverModifier = 0, this.arrivalTime = '--:--', this.isMuted = false, this.isCameraLocked = true, this.mapTheme = MapThemeType.vectorLight, this.markers = const {}, this.polylines = const {}, this.searchResults = const [], this.isSelectingLocationOnMap = false, this.activePickerMode, this.pickedLocation, this.isOnline = true, this.errorMessage, this.selectedVehicleColor = 0xFF007AFF, this.selectedVehicleStyle = 'car', this.vehicleScale = 1.8, this.recentSearches = const [], this.isSearching = false, this.isOrbiting = false, this.orbitSpeed = 1.0, this.isSunPlaying = false, this.sunTimeMinutes = 1110, this.terrainExaggeration = 2.0, this.cameraTilt = 55.0, this.showBuildings = true, this.showContours = true, this.showHillshading = true, this.isTouristModeEnabled = false, this.selectedLandmarkId, }); RouteData? get currentRoute => routes.isNotEmpty && selectedRouteIndex < routes.length ? routes[selectedRouteIndex] : null; bool get isNavigating => status == NavigationStatus.navigating; String get formattedRemainingDistance { if (remainingDistance >= 1000) { return '${(remainingDistance / 1000).toStringAsFixed(1)} كم'; } return '${remainingDistance.round()} م'; } String get formattedRemainingDuration { final int minutes = (remainingDuration / 60).round(); if (minutes >= 60) { final int hours = minutes ~/ 60; final int remMin = minutes % 60; return '$hours س $remMin د'; } return '$minutes دقيقة'; } String get formattedDistanceToStep { if (distanceToNextStep >= 1000) { return '${(distanceToNextStep / 1000).toStringAsFixed(1)} كم'; } if (distanceToNextStep > 0) { return '${distanceToNextStep.round()} م'; } return ''; } NavigationState copyWith({ NavigationStatus? status, LatLng? myLocation, double? altitude, double? heading, double? speed, List? routes, int? selectedRouteIndex, LatLng? destination, String? destinationTitle, String? originTitle, List>? routeSteps, int? currentStepIndex, String? currentInstruction, String? nextInstruction, double? distanceToNextStep, double? remainingDistance, double? remainingDuration, int? currentManeuverModifier, String? arrivalTime, bool? isMuted, bool? isCameraLocked, MapThemeType? mapTheme, Set? markers, Set? polylines, List? searchResults, bool? isSelectingLocationOnMap, String? activePickerMode, bool clearActivePickerMode = false, LatLng? pickedLocation, bool clearPickedLocation = false, bool? isOnline, String? errorMessage, int? selectedVehicleColor, String? selectedVehicleStyle, double? vehicleScale, List? recentSearches, bool? isSearching, bool? isOrbiting, double? orbitSpeed, bool? isSunPlaying, int? sunTimeMinutes, double? terrainExaggeration, double? cameraTilt, bool? showBuildings, bool? showContours, bool? showHillshading, bool? isTouristModeEnabled, String? selectedLandmarkId, bool clearSelectedLandmark = false, }) { return NavigationState( status: status ?? this.status, myLocation: myLocation ?? this.myLocation, altitude: altitude ?? this.altitude, heading: heading ?? this.heading, speed: speed ?? this.speed, routes: routes ?? this.routes, selectedRouteIndex: selectedRouteIndex ?? this.selectedRouteIndex, destination: destination ?? this.destination, destinationTitle: destinationTitle ?? this.destinationTitle, originTitle: originTitle ?? this.originTitle, routeSteps: routeSteps ?? this.routeSteps, currentStepIndex: currentStepIndex ?? this.currentStepIndex, currentInstruction: currentInstruction ?? this.currentInstruction, nextInstruction: nextInstruction ?? this.nextInstruction, distanceToNextStep: distanceToNextStep ?? this.distanceToNextStep, remainingDistance: remainingDistance ?? this.remainingDistance, remainingDuration: remainingDuration ?? this.remainingDuration, currentManeuverModifier: currentManeuverModifier ?? this.currentManeuverModifier, arrivalTime: arrivalTime ?? this.arrivalTime, isMuted: isMuted ?? this.isMuted, isCameraLocked: isCameraLocked ?? this.isCameraLocked, mapTheme: mapTheme ?? this.mapTheme, markers: markers ?? this.markers, polylines: polylines ?? this.polylines, searchResults: searchResults ?? this.searchResults, isSelectingLocationOnMap: isSelectingLocationOnMap ?? this.isSelectingLocationOnMap, activePickerMode: clearActivePickerMode ? null : (activePickerMode ?? this.activePickerMode), pickedLocation: clearPickedLocation ? null : (pickedLocation ?? this.pickedLocation), isOnline: isOnline ?? this.isOnline, errorMessage: errorMessage ?? this.errorMessage, selectedVehicleColor: selectedVehicleColor ?? this.selectedVehicleColor, selectedVehicleStyle: selectedVehicleStyle ?? this.selectedVehicleStyle, vehicleScale: vehicleScale ?? this.vehicleScale, recentSearches: recentSearches ?? this.recentSearches, isSearching: isSearching ?? this.isSearching, isOrbiting: isOrbiting ?? this.isOrbiting, orbitSpeed: orbitSpeed ?? this.orbitSpeed, isSunPlaying: isSunPlaying ?? this.isSunPlaying, sunTimeMinutes: sunTimeMinutes ?? this.sunTimeMinutes, terrainExaggeration: terrainExaggeration ?? this.terrainExaggeration, cameraTilt: cameraTilt ?? this.cameraTilt, showBuildings: showBuildings ?? this.showBuildings, showContours: showContours ?? this.showContours, showHillshading: showHillshading ?? this.showHillshading, isTouristModeEnabled: isTouristModeEnabled ?? this.isTouristModeEnabled, selectedLandmarkId: clearSelectedLandmark ? null : (selectedLandmarkId ?? this.selectedLandmarkId), ); } @override List get props => [ status, myLocation, altitude, heading, speed, routes, selectedRouteIndex, destination, destinationTitle, originTitle, routeSteps, currentStepIndex, currentInstruction, nextInstruction, distanceToNextStep, remainingDistance, remainingDuration, currentManeuverModifier, arrivalTime, isMuted, isCameraLocked, mapTheme, markers, polylines, searchResults, isSelectingLocationOnMap, activePickerMode, pickedLocation, isOnline, errorMessage, selectedVehicleColor, selectedVehicleStyle, vehicleScale, recentSearches, isSearching, isOrbiting, orbitSpeed, isSunPlaying, sunTimeMinutes, terrainExaggeration, cameraTilt, showBuildings, showContours, showHillshading, isTouristModeEnabled, selectedLandmarkId, ]; }