// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'configuration.dart';
import 'match.dart';
import 'path_utils.dart';

/// Converts a location into a list of [RouteMatch] objects.
class RouteMatcher {
  /// [RouteMatcher] constructor.
  RouteMatcher(this.configuration);

  /// The route configuration.
  final RouteConfiguration configuration;

  /// Finds the routes that matched the given URL.
  RouteMatchList findMatch(String location, {Object? extra}) {
    final String canonicalLocation = canonicalUri(location);
    final List<RouteMatch> matches =
        _getLocRouteMatches(canonicalLocation, extra);
    return RouteMatchList(matches);
  }

  List<RouteMatch> _getLocRouteMatches(String location, Object? extra) {
    final Uri uri = Uri.parse(location);
    final List<RouteMatch> result = _getLocRouteRecursively(
      loc: uri.path,
      restLoc: uri.path,
      routes: configuration.routes,
      parentFullpath: '',
      parentSubloc: '',
      queryParams: uri.queryParameters,
      extra: extra,
    );

    if (result.isEmpty) {
      throw MatcherError('no routes for location', location);
    }

    return result;
  }
}

/// The list of [RouteMatch] objects.
class RouteMatchList {
  /// RouteMatchList constructor.
  RouteMatchList(this._matches);

  /// Constructs an empty matches object.
  factory RouteMatchList.empty() => RouteMatchList(<RouteMatch>[]);

  final List<RouteMatch> _matches;

  /// Returns true if there are no matches.
  bool get isEmpty => _matches.isEmpty;

  /// Returns true if there are matches.
  bool get isNotEmpty => _matches.isNotEmpty;

  /// The original URL that was matched.
  Uri get location =>
      _matches.isEmpty ? Uri() : Uri.parse(_matches.last.fullUriString);

  /// Pushes a match onto the list of matches.
  void push(RouteMatch match) {
    _matches.add(match);
  }

  /// Removes the last match.
  void pop() {
    _matches.removeLast();
    assert(
        _matches.isNotEmpty,
        'You have popped the last page off of the stack,'
        ' there are no pages left to show');
  }

  /// Returns true if [pop] can safely be called.
  bool canPop() {
    return _matches.length > 1;
  }

  /// An optional object provided by the app during navigation.
  Object? get extra => _matches.last.extra;

  /// The last matching route.
  RouteMatch get last => _matches.last;

  /// The route matches.
  List<RouteMatch> get matches => _matches;

  /// Returns true if the current match intends to display an error screen.
  bool get isError => matches.length == 1 && matches.first.error != null;

  /// Returns the error that this match intends to display.
  Exception? get error => matches.first.error;
}

/// An error that occurred during matching.
class MatcherError extends Error {
  /// Constructs a [MatcherError].
  MatcherError(String message, this.location)
      : message = message + ': $location';

  /// The error message.
  final String message;

  /// The location that failed to match.
  final String location;

  @override
  String toString() {
    return message;
  }
}

List<RouteMatch> _getLocRouteRecursively({
  required String loc,
  required String restLoc,
  required String parentSubloc,
  required List<GoRoute> routes,
  required String parentFullpath,
  required Map<String, String> queryParams,
  required Object? extra,
}) {
  bool debugGatherAllMatches = false;
  assert(() {
    debugGatherAllMatches = true;
    return true;
  }());
  final List<List<RouteMatch>> result = <List<RouteMatch>>[];
  // find the set of matches at this level of the tree
  for (final GoRoute route in routes) {
    final String fullpath = concatenatePaths(parentFullpath, route.path);
    final RouteMatch? match = RouteMatch.match(
      route: route,
      restLoc: restLoc,
      parentSubloc: parentSubloc,
      fullpath: fullpath,
      queryParams: queryParams,
      extra: extra,
    );

    if (match == null) {
      continue;
    }
    if (match.subloc.toLowerCase() == loc.toLowerCase()) {
      // If it is a complete match, then return the matched route
      // NOTE: need a lower case match because subloc is canonicalized to match
      // the path case whereas the location can be of any case and still match
      result.add(<RouteMatch>[match]);
    } else if (route.routes.isEmpty) {
      // If it is partial match but no sub-routes, bail.
      continue;
    } else {
      // Otherwise, recurse
      final String childRestLoc =
          loc.substring(match.subloc.length + (match.subloc == '/' ? 0 : 1));
      assert(loc.startsWith(match.subloc));
      assert(restLoc.isNotEmpty);

      final List<RouteMatch> subRouteMatch = _getLocRouteRecursively(
        loc: loc,
        restLoc: childRestLoc,
        parentSubloc: match.subloc,
        routes: route.routes,
        parentFullpath: fullpath,
        queryParams: queryParams,
        extra: extra,
      ).toList();

      // If there's no sub-route matches, there is no match for this location
      if (subRouteMatch.isEmpty) {
        continue;
      }
      result.add(<RouteMatch>[match, ...subRouteMatch]);
    }
    // Should only reach here if there is a match.
    if (debugGatherAllMatches) {
      continue;
    } else {
      break;
    }
  }

  if (result.isEmpty) {
    return <RouteMatch>[];
  }

  // If there are multiple routes that match the location, returning the first one.
  // To make predefined routes to take precedence over dynamic routes eg. '/:id'
  // consider adding the dynamic route at the end of the routes
  return result.first;
}
