import 'package:flutter/material.dart';
import 'package:get/get_navigation/src/root/parse_route.dart';
import 'package:guru_utils/extensions/extensions.dart';
import 'package:guru_utils/log/log.dart';

class RouteRecorder extends NavigatorObserver {

  static final RouteRecorder instance = RouteRecorder._();

  RouteRecorder._();

  final _historySubject = BehaviorSubject<List<Route>>.seeded([]);

  final List<Route> _removeManualRoutes = [];

  Route? filter(bool Function(Route) isMatch) {
    return _historySubject.value.firstWhereOrNull((element) => isMatch(element));
  }

  void removeRoute<T>(RoutePredicate predicate, [T? result]) {
    // 需要新创建一个列表，否则会报错 ConcurrentModifyException
    for (var route in List.of(_historySubject.value.where((e) => predicate(e)))) {
      if (_removeManualRoutes.contains(route)) {
        continue;
      }
      _removeManualRoutes.add(route);
      // TODO didPop error occur
      // 在移除route前手动调用此方法去完成Future
      // route.didPop(result);
      // UI上的移除
      route.navigator?.removeRoute(route);
    }
  }

  void _checkDispose() {
    final history = _historySubject.value;
    int beforeLength = history.length;
    List.of(_historySubject.value.where((element) => !element.isActive)).forEach((element) {
      history.remove(element);
    });
    if (history.length < beforeLength) {
      Log.d('_checkDispose remove not active route', tag: 'RouteRecorder');
      _historySubject.add(history);
    }
  }

  @override
  void didPush(Route route, Route? previousRoute) {
    Log.d('didPush ${route.settings.name}', tag: 'RouteRecorder');
    _checkDispose();
    _historySubject.add(_historySubject.value..add(route));
  }

  @override
  void didReplace({Route? newRoute, Route? oldRoute}) {
    final history = _historySubject.value;
    history.remove(oldRoute);
    if (newRoute != null) {
      history.add(newRoute);
    }
    _historySubject.add(history);
  }

  @override
  void didPop(Route route, Route? previousRoute) {
    Log.d('didPop ${route.settings.name}', tag: 'RouteRecorder');
    _checkDispose();
    _historySubject.add(_historySubject.value..remove(route));
    _removeManualRoutes.remove(route);
  }

  @override
  void didRemove(Route route, Route? previousRoute) {
    Log.d('didRemove ${route.settings.name}', tag: 'RouteRecorder');
    _historySubject.add(_historySubject.value..remove(route));
  }
}