// 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 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';

import 'matching.dart';
import 'path_utils.dart';
import 'route.dart';

///  An instance of a GoRoute plus information about the current location.
class RouteMatch {
  /// Constructor for [RouteMatch].
  RouteMatch({
    required this.route,
    required this.subloc,
    required this.fullpath,
    required this.encodedParams,
    required this.queryParams,
    required this.queryParametersAll,
    required this.extra,
    required this.error,
    this.pageKey,
  })  : fullUriString = _addQueryParams(subloc, queryParametersAll),
        assert(Uri.parse(subloc).queryParameters.isEmpty),
        assert(Uri.parse(fullpath).queryParameters.isEmpty),
        assert(() {
          for (final MapEntry<String, String> p in encodedParams.entries) {
            assert(p.value == Uri.encodeComponent(Uri.decodeComponent(p.value)),
                'encodedParams[${p.key}] is not encoded properly: "${p.value}"');
          }
          return true;
        }());

  // ignore: public_member_api_docs
  static RouteMatch? match({
    required RouteBase route,
    required String restLoc, // e.g. person/p1
    required String parentSubloc, // e.g. /family/f2
    required String fullpath, // e.g. /family/:fid/person/:pid
    required Map<String, String> queryParams,
    required Map<String, List<String>> queryParametersAll,
    required Object? extra,
  }) {
    if (route is ShellRoute) {
      return RouteMatch(
        route: route,
        subloc: restLoc,
        fullpath: '',
        encodedParams: <String, String>{},
        queryParams: queryParams,
        queryParametersAll: queryParametersAll,
        extra: extra,
        error: null,
        // Provide a unique pageKey to ensure that the page for this ShellRoute is
        // reused.
        pageKey: ValueKey<String>(route.hashCode.toString()),
      );
    } else if (route is GoRoute) {
      assert(!route.path.contains('//'));

      final RegExpMatch? match = route.matchPatternAsPrefix(restLoc);
      if (match == null) {
        return null;
      }

      final Map<String, String> encodedParams = route.extractPathParams(match);
      final String pathLoc = patternToPath(route.path, encodedParams);
      final String subloc = concatenatePaths(parentSubloc, pathLoc);
      return RouteMatch(
        route: route,
        subloc: subloc,
        fullpath: fullpath,
        encodedParams: encodedParams,
        queryParams: queryParams,
        queryParametersAll: queryParametersAll,
        extra: extra,
        error: null,
      );
    }
    throw MatcherError('Unexpected route type: $route', restLoc);
  }

  /// The matched route.
  final RouteBase route;

  /// The matched location.
  final String subloc; // e.g. /family/f2

  /// The matched template.
  final String fullpath; // e.g. /family/:fid

  /// Parameters for the matched route, URI-encoded.
  final Map<String, String> encodedParams;

  /// The URI query split into a map according to the rules specified for FORM
  /// post in the [HTML 4.01 specification section
  /// 17.13.4](https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
  /// "HTML 4.01 section 17.13.4").
  ///
  /// If a key occurs more than once in the query string, it is mapped to an
  /// arbitrary choice of possible value.
  ///
  /// If the request is `a/b/?q1=v1&q2=v2&q2=v3`, then [queryParameter] will be
  /// `{q1: 'v1', q2: 'v2'}`.
  ///
  /// See also
  /// * [queryParametersAll] that can provide a map that maps keys to all of
  ///   their values.
  final Map<String, String> queryParams;

  /// Returns the URI query split into a map according to the rules specified
  /// for FORM post in the [HTML 4.01 specification section
  /// 17.13.4](https://www.w3.org/TR/REC-html40/interact/forms.html#h-17.13.4
  /// "HTML 4.01 section 17.13.4").
  ///
  /// Keys are mapped to lists of their values. If a key occurs only once, its
  /// value is a singleton list. If a key occurs with no value, the empty string
  /// is used as the value for that occurrence.
  ///
  /// If the request is `a/b/?q1=v1&q2=v2&q2=v3`, then [queryParameterAll] with
  /// be `{q1: ['v1'], q2: ['v2', 'v3']}`.
  final Map<String, List<String>> queryParametersAll;

  /// An extra object to pass along with the navigation.
  final Object? extra;

  /// An exception if there was an error during matching.
  final Exception? error;

  /// Optional value key of type string, to hold a unique reference to a page.
  final ValueKey<String>? pageKey;

  /// The full uri string
  final String fullUriString; // e.g. /family/12?query=14

  static String _addQueryParams(
      String loc, Map<String, dynamic> queryParametersAll) {
    final Uri uri = Uri.parse(loc);
    assert(uri.queryParameters.isEmpty);
    return Uri(
            path: uri.path,
            queryParameters:
                queryParametersAll.isEmpty ? null : queryParametersAll)
        .toString();
  }

  /// Parameters for the matched route, URI-decoded.
  Map<String, String> get decodedParams => <String, String>{
        for (final MapEntry<String, String> param in encodedParams.entries)
          param.key: Uri.decodeComponent(param.value)
      };

  /// For use by the Router architecture as part of the RouteMatch
  @override
  String toString() => 'RouteMatch($fullpath, $encodedParams)';
}
