import "package:a_star/a_star.dart";
import "package:shared/data.dart";

import "state.dart";

void printStops(Iterable<Stop> stops) {
  log("Found stops:");
  for (final stop in stops) {
    log("- ${stop.routes}, ${stop.name}");
  }
}

Iterable<StopState>? findPath(Coordinates start, Coordinates end) {
  // 1) Find [numStops] nearest stops by the given locations
  log("Finding nearest stops...");
  final startStops = StopState.findStopsNear(start);
  printStops(startStops);
  final endStops = StopState.findStopsNear(end);
  printStops(endStops);

  // 2) Use A* to find a route with transfers
  log("Using A*");
  final paths = <Iterable<StopState>>[];
  for (final startStop in startStops) {
    for (final startRouteID in startStop.routeIDs) {
      for (final endStop in endStops) {
        final state = StopState.start(
          stopID: startStop.id,
          goalID: endStop.id,
          routeID: startRouteID,
          startPoint: start,
          endPoint: end,
        );
        log("Finding a route using ${state.hash()}");
        final result = aStar(state, limit: 1000, verbose: false);
        if (result == null) continue;
        paths.add(result.reconstructPath());
      }
    }
  }

  if (paths.isEmpty) return null;
  return paths.min(getTotalDistance);
}

double getTotalDistance(Iterable<StopState> path) =>
  path.sum((step) => step.distanceWalked);
