// Copyright 2014 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:vector_math/vector_math_64.dart';

import 'events.dart';

/// A callback that receives a [PointerEvent]
typedef PointerRoute = void Function(PointerEvent event);

/// A routing table for [PointerEvent] events.
class PointerRouter {
  final Map<int, Map<PointerRoute, Matrix4?>> _routeMap = <int, Map<PointerRoute, Matrix4?>>{};
  final Map<PointerRoute, Matrix4?> _globalRoutes = <PointerRoute, Matrix4?>{};

  /// Adds a route to the routing table.
  ///
  /// Whenever this object routes a [PointerEvent] corresponding to
  /// pointer, call route.
  ///
  /// Routes added reentrantly within [PointerRouter.route] will take effect when
  /// routing the next event.
  void addRoute(int pointer, PointerRoute route, [Matrix4? transform]) {
    final Map<PointerRoute, Matrix4?> routes = _routeMap.putIfAbsent(
      pointer,
      () => <PointerRoute, Matrix4?>{},
    );
    assert(!routes.containsKey(route));
    routes[route] = transform;
  }

  /// Removes a route from the routing table.
  ///
  /// No longer call route when routing a [PointerEvent] corresponding to
  /// pointer. Requires that this route was previously added to the router.
  ///
  /// Routes removed reentrantly within [PointerRouter.route] will take effect
  /// immediately.
  void removeRoute(int pointer, PointerRoute route) {
    assert(_routeMap.containsKey(pointer));
    final Map<PointerRoute, Matrix4?> routes = _routeMap[pointer]!;
    assert(routes.containsKey(route));
    routes.remove(route);
    if (routes.isEmpty)
      _routeMap.remove(pointer);
  }

  /// Adds a route to the global entry in the routing table.
  ///
  /// Whenever this object routes a [PointerEvent], call route.
  ///
  /// Routes added reentrantly within [PointerRouter.route] will take effect when
  /// routing the next event.
  void addGlobalRoute(PointerRoute route, [Matrix4? transform]) {
    assert(!_globalRoutes.containsKey(route));
    _globalRoutes[route] = transform;
  }

  /// Removes a route from the global entry in the routing table.
  ///
  /// No longer call route when routing a [PointerEvent]. Requires that this
  /// route was previously added via [addGlobalRoute].
  ///
  /// Routes removed reentrantly within [PointerRouter.route] will take effect
  /// immediately.
  void removeGlobalRoute(PointerRoute route) {
    assert(_globalRoutes.containsKey(route));
    _globalRoutes.remove(route);
  }

  /// The number of global routes that have been registered.
  ///
  /// This is valid in debug builds only. In release builds, this will throw an
  /// [UnsupportedError].
  int get debugGlobalRouteCount {
    int? count;
    assert(() {
      count = _globalRoutes.length;
      return true;
    }());
    if (count != null) {
      return count!;
    }
    throw UnsupportedError('debugGlobalRouteCount is not supported in release builds');
  }

  @pragma('vm:notify-debugger-on-exception')
  void _dispatch(PointerEvent event, PointerRoute route, Matrix4? transform) {
    try {
      event = event.transformed(transform);
      route(event);
    } catch (exception, stack) {
      InformationCollector? collector;
      assert(() {
        collector = () sync* {
          yield DiagnosticsProperty<PointerRouter>('router', this, level: DiagnosticLevel.debug);
          yield DiagnosticsProperty<PointerRoute>('route', route, level: DiagnosticLevel.debug);
          yield DiagnosticsProperty<PointerEvent>('event', event, level: DiagnosticLevel.debug);
        };
        return true;
      }());
      FlutterError.reportError(FlutterErrorDetails(
        exception: exception,
        stack: stack,
        library: 'gesture library',
        context: ErrorDescription('while routing a pointer event'),
        informationCollector: collector,
      ));
    }
  }

  /// Calls the routes registered for this pointer event.
  ///
  /// Routes are called in the order in which they were added to the
  /// PointerRouter object.
  void route(PointerEvent event) {
    final Map<PointerRoute, Matrix4?>? routes = _routeMap[event.pointer];
    final Map<PointerRoute, Matrix4?> copiedGlobalRoutes = Map<PointerRoute, Matrix4?>.from(_globalRoutes);
    if (routes != null) {
      _dispatchEventToRoutes(
        event,
        routes,
        Map<PointerRoute, Matrix4?>.from(routes),
      );
    }
    _dispatchEventToRoutes(event, _globalRoutes, copiedGlobalRoutes);
  }

  void _dispatchEventToRoutes(
    PointerEvent event,
    Map<PointerRoute, Matrix4?> referenceRoutes,
    Map<PointerRoute, Matrix4?> copiedRoutes,
  ) {
    copiedRoutes.forEach((PointerRoute route, Matrix4? transform) {
      if (referenceRoutes.containsKey(route)) {
        _dispatch(event, route, transform);
      }
    });
  }
}
