import 'package:anyway/domain/entities/landmark.dart'; import 'package:anyway/domain/entities/preferences.dart'; import 'package:anyway/domain/entities/trip.dart'; import 'package:anyway/domain/repositories/trip_repository.dart'; import 'package:anyway/data/datasources/trip_remote_datasource.dart'; class BackendTripRepository implements TripRepository { final TripRemoteDataSource remote; BackendTripRepository({required this.remote}); @override Future getTrip({Preferences? preferences, String? tripUUID, List? landmarks}) async { try { Map json; if (tripUUID != null) { json = await remote.fetchTrip(tripUUID); } else { if (preferences == null) { throw ArgumentError('Either preferences or tripUUID must be provided'); } final Map prefsPayload = _buildPreferencesPayload(preferences); List> landmarkBodies = landmarks != null ? landmarks.map((lm) => lm.toJson()).toList() : await _fetchLandmarkPayloads(prefsPayload, preferences.startLocation); // TODO: remove // restrict the landmark list to 30 to iterate quickly landmarkBodies = landmarkBodies.take(30).toList(); // change the json key because of backend inconsistency for (var lm in landmarkBodies) { if (lm.containsKey('type')) { lm['type'] = "sightseeing"; } lm['osm_type'] = 'node'; lm['osm_id'] = 1; } final Map body = { 'preferences': prefsPayload, 'landmarks': landmarkBodies, 'start': preferences.startLocation, }; if (preferences.endLocation != null) { body['end'] = preferences.endLocation; } if (preferences.detourToleranceMinutes != null) { body['detour_tolerance_minute'] = preferences.detourToleranceMinutes; } json = await remote.createTrip(body); } return Trip.fromJson(json); } catch (e) { throw Exception('Failed to fetch trip: ${e.toString()}'); } } // TODO - maybe shorten this @override Future> searchLandmarks(Preferences preferences) async { final Map prefsPayload = _buildPreferencesPayload(preferences); final List> rawLandmarks = await _fetchLandmarkPayloads(prefsPayload, preferences.startLocation); return rawLandmarks.map((lmJson) => Landmark.fromJson(lmJson)).toList(); } Future>> _fetchLandmarkPayloads( Map prefsPayload, List startLocation) async { final Map landmarkRequest = { 'preferences': prefsPayload, 'start': startLocation, }; return await remote.fetchLandmarks(landmarkRequest); } Map _buildPreferencesPayload(Preferences preferences) { final Map prefsPayload = {}; preferences.scores.forEach((type, score) { prefsPayload[type] = {'type': type, 'score': score}; }); prefsPayload['max_time_minute'] = preferences.maxTimeMinutes; return prefsPayload; } }