// 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 'logging.dart';
import 'match.dart';
import 'matching.dart';

/// A GoRouter redirector function.
// TODO(johnpryan): make redirector async
// See https://github.com/flutter/flutter/issues/105808
typedef RouteRedirector = RouteMatchList Function(RouteMatchList matches,
    RouteConfiguration configuration, RouteMatcher matcher,
    {Object? extra});

/// Processes redirects by returning a new [RouteMatchList] representing the new
/// location.
RouteMatchList redirect(RouteMatchList prevMatchList,
    RouteConfiguration configuration, RouteMatcher matcher,
    {Object? extra}) {
  RouteMatchList matches;

  // Store each redirect to detect loops
  final List<RouteMatchList> redirects = <RouteMatchList>[prevMatchList];

  // Keep looping until redirecting is done
  while (true) {
    final RouteMatchList currentMatches = redirects.last;

    // Check for top-level redirect
    final Uri uri = currentMatches.location;
    final String? topRedirectLocation = configuration.topRedirect(
      GoRouterState(
        configuration,
        location: currentMatches.location.toString(),
        name: null,
        // No name available at the top level trim the query params off the
        // sub-location to match route.redirect
        subloc: uri.path,
        queryParams: uri.queryParameters,
        extra: extra,
      ),
    );

    if (topRedirectLocation != null) {
      final RouteMatchList newMatch = matcher.findMatch(topRedirectLocation);
      _addRedirect(redirects, newMatch, prevMatchList.location,
          configuration.redirectLimit);
      continue;
    }

    // If there's no top-level redirect, keep the matches the same as before.
    matches = currentMatches;

    // Merge new params to keep params from previously matched paths, e.g.
    // /users/:userId/book/:bookId provides userId and bookId to book/:bookId
    Map<String, String> previouslyMatchedParams = <String, String>{};
    for (final RouteMatch match in currentMatches.matches) {
      assert(
        !previouslyMatchedParams.keys.any(match.encodedParams.containsKey),
        'Duplicated parameter names',
      );
      match.encodedParams.addAll(previouslyMatchedParams);
      previouslyMatchedParams = match.encodedParams;
    }

    // check top route for redirect
    final RouteMatch? top = matches.isNotEmpty ? matches.last : null;
    if (top == null) {
      break;
    }
    final String? topRouteLocation = top.route.redirect(
      GoRouterState(
        configuration,
        location: currentMatches.location.toString(),
        subloc: top.subloc,
        name: top.route.name,
        path: top.route.path,
        fullpath: top.fullpath,
        extra: top.extra,
        params: top.decodedParams,
        queryParams: top.queryParams,
      ),
    );

    if (topRouteLocation == null) {
      break;
    }

    final RouteMatchList newMatchList = matcher.findMatch(topRouteLocation);
    _addRedirect(redirects, newMatchList, prevMatchList.location,
        configuration.redirectLimit);
    continue;
  }
  return matches;
}

/// A configuration error detected while processing redirects.
class RedirectionError extends Error implements UnsupportedError {
  /// RedirectionError constructor.
  RedirectionError(this.message, this.matches, this.location);

  /// The matches that were found while processing redirects.
  final List<RouteMatchList> matches;

  @override
  final String message;

  /// The location that was originally navigated to, before redirection began.
  final Uri location;

  @override
  String toString() => '${super.toString()} ${<String>[
        ...matches.map(
            (RouteMatchList routeMatches) => routeMatches.location.toString()),
      ].join(' => ')}';
}

/// Adds the redirect to [redirects] if it is valid.
void _addRedirect(List<RouteMatchList> redirects, RouteMatchList newMatch,
    Uri prevLocation, int redirectLimit) {
  // Verify that the redirect can be parsed and is not already
  // in the list of redirects
  assert(() {
    if (redirects.contains(newMatch)) {
      throw RedirectionError('redirect loop detected',
          <RouteMatchList>[...redirects, newMatch], prevLocation);
    }
    if (redirects.length > redirectLimit) {
      throw RedirectionError('too many redirects',
          <RouteMatchList>[...redirects, newMatch], prevLocation);
    }
    return true;
  }());

  redirects.add(newMatch);

  assert(() {
    log.info('redirecting to $newMatch');
    return true;
  }());
}
