// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of app;

/// The observatory application. Instances of this are created and owned
/// by the observatory_application custom element.
class ObservatoryApplication {
  static late ObservatoryApplication app;
  final RenderingQueue queue = new RenderingQueue();
  final TargetRepository targets = new TargetRepository(isConnectedVMTarget);
  final EventRepository events = new EventRepository();
  final NotificationRepository notifications = new NotificationRepository();
  final _pageRegistry = <Page>[];
  late LocationManager _locationManager;
  LocationManager get locationManager => _locationManager;
  Page? currentPage;
  bool _vmConnected = false;
  VM? _vm;
  VM get vm => _vm!;

  static bool isConnectedVMTarget(M.Target target) {
    if (app._vm is CommonWebSocketVM) {
      if ((app._vm as CommonWebSocketVM).target == target) {
        return app._vm!.isConnected;
      }
    }
    return false;
  }

  _switchVM(VM? newVM) {
    final VM? oldVM = _vm;

    Logger.root.info('_switchVM from:${oldVM} to:${newVM}');

    if (oldVM == newVM) {
      // Do nothing.
      return;
    }

    if (oldVM != null) {
      print('disconnecting from the old VM ${oldVM}--');
      // Disconnect from current VM.
      stopGCEventListener();
      notifications.deleteAll();
      oldVM.disconnect();
    }

    if (newVM != null) {
      // Mark that we haven't connected yet.
      _vmConnected = false;
      // On connect:
      newVM.onConnect.then((_) async {
        // We connected.
        _vmConnected = true;
        notifications.deleteDisconnectEvents();
        await newVM.load();
        // TODO(cbernaschina) smart connection of streams in the events object.
        newVM.listenEventStream(VM.kVMStream, _onEvent);
        newVM.listenEventStream(VM.kIsolateStream, _onEvent);
        newVM.listenEventStream(VM.kDebugStream, _onEvent);
        newVM.listenEventStream(VM.kServiceStream, _onEvent);
      });
      // On disconnect:
      newVM.onDisconnect.then((String reason) {
        if (this.vm != newVM) {
          // This disconnect event occurred *after* a new VM was installed.
          return;
        }
        // Let anyone looking at the targets know that we have disconnected
        // from one.
        targets.emitDisconnectEvent();
        if (!_vmConnected) {
          // Connection error. Navigate back to the connect page.
          Logger.root.info('Connection failed, navigating to VM connect page.');
          // Clear the vm.
          _vm = null;
          app.locationManager.go(Uris.vmConnect());
        } else {
          // Disconnect. Stay at the current page and push an a connection
          // closed event.
          Logger.root.info('Lost an existing connection to a VM');
          events.add(new ConnectionClosedEvent(new DateTime.now(), reason));
        }
      });
    }

    _vm = newVM;
  }

  StreamSubscription? _gcSubscription;
  StreamSubscription? _loggingSubscription;

  Future startGCEventListener() async {
    if (_gcSubscription != null || _vm == null) {
      return;
    }
    _gcSubscription = await _vm!.listenEventStream(VM.kGCStream, _onEvent);
  }

  Future startLoggingEventListener() async {
    if (_loggingSubscription != null || _vm == null) {
      return;
    }
    _loggingSubscription =
        await _vm!.listenEventStream(Isolate.kLoggingStream, _onEvent);
  }

  Future stopGCEventListener() async {
    if (_gcSubscription == null) {
      return;
    }
    _gcSubscription!.cancel();
    _gcSubscription = null;
  }

  Future stopLoggingEventListener() async {
    if (_loggingSubscription == null) {
      return;
    }
    _loggingSubscription!.cancel();
    _loggingSubscription = null;
  }

  final ObservatoryApplicationElement rootElement;

  ServiceObject? lastErrorOrException;

  void _initOnce() {
    app = this;
    _registerPages();
    // Visit the current page.
    locationManager._visit();
  }

  void _deletePauseEvents(e) {
    notifications.deletePauseEvents(isolate: e.isolate);
  }

  void _addNotification(M.Event e) {
    notifications.add(new EventNotification(e));
  }

  void _onEvent(ServiceEvent event) {
    assert(event.kind != ServiceEvent.kNone);
    M.Event? e = createEventFromServiceEvent(event);
    if (e != null) {
      events.add(e);
    }
  }

  void _registerPages() {
    _pageRegistry.add(new VMPage(this));
    _pageRegistry.add(new FlagsPage(this));
    _pageRegistry.add(new NativeMemoryProfilerPage(this));
    _pageRegistry.add(new InspectPage(this));
    _pageRegistry.add(new ClassTreePage(this));
    _pageRegistry.add(new DebuggerPage(this));
    _pageRegistry.add(new ObjectStorePage(this));
    _pageRegistry.add(new CpuProfilerPage(this));
    _pageRegistry.add(new TableCpuProfilerPage(this));
    _pageRegistry.add(new AllocationProfilerPage(this));
    _pageRegistry.add(new HeapMapPage(this));
    _pageRegistry.add(new HeapSnapshotPage(this));
    _pageRegistry.add(new VMConnectPage(this));
    _pageRegistry.add(new IsolateReconnectPage(this));
    _pageRegistry.add(new ErrorViewPage(this));
    _pageRegistry.add(new MetricsPage(this));
    _pageRegistry.add(new PersistentHandlesPage(this));
    _pageRegistry.add(new PortsPage(this));
    _pageRegistry.add(new LoggingPage(this));
    _pageRegistry.add(new TimelinePage(this));
    _pageRegistry.add(new TimelineDashboardPage(this));
    _pageRegistry.add(new ProcessSnapshotPage(this));
    // Note that ErrorPage must be the last entry in the list as it is
    // the catch all.
    _pageRegistry.add(new ErrorPage(this));
  }

  void _visit(Uri uri, Map<String, String> internalArguments) {
    if (internalArguments['trace'] != null) {
      var traceArg = internalArguments['trace'];
      if (traceArg == 'on') {
        Tracer.start();
      } else if (traceArg == 'off') {
        Tracer.stop();
      }
    }
    if (Tracer.current != null) {
      Tracer.current!.reset();
    }
    for (var i = 0; i < _pageRegistry.length; i++) {
      var page = _pageRegistry[i];
      if (page.canVisit(uri)) {
        _installPage(page);
        page.visit(uri, internalArguments);
        return;
      }
    }
    throw new ArgumentError.value(uri, 'uri');
  }

  /// Set the Observatory application page.
  void _installPage(Page page) {
    assert(page != null);
    if (currentPage == page) {
      // Already installed.
      return;
    }
    if (currentPage != null) {
      Logger.root.info('Uninstalling page: $currentPage');
      currentPage!.onUninstall();
      // Clear children.
      rootElement.children.clear();
    }
    Logger.root.info('Installing page: $page');
    try {
      page.onInstall();
    } catch (e) {
      Logger.root.severe('Failed to install page: $e');
    }
    // Add new page.
    rootElement.children.add(page.element!);

    // Remember page.
    currentPage = page;
  }

  ObservatoryApplication(this.rootElement) {
    _locationManager = new LocationManager(this);
    targets.onChange.listen((TargetChangeEvent e) {
      if (e.disconnected) {
        // We don't care about disconnected events.
        return;
      }
      if (targets.current == null) {
        _switchVM(null);
      } else {
        final bool currentTarget =
            (_vm as WebSocketVM?)?.target == targets.current;
        final bool currentTargetConnected = (_vm != null) && _vm!.isConnected;
        if (!currentTarget || !currentTargetConnected) {
          _switchVM(new WebSocketVM(targets.current!));
          _vm!.onConnect.then((_) {
            app.locationManager.go(Uris.vm());
          });
          _vm!.load();
        } else if (currentTargetConnected) {
          app.locationManager.go(Uris.vm());
        }
      }
    });

    Logger.root.info('Setting initial target to ${targets.current!.name}');
    _switchVM(new WebSocketVM(targets.current!));
    _initOnce();

    // delete pause events.
    events.onIsolateExit.listen(_deletePauseEvents);
    events.onResume.listen(_deletePauseEvents);
    events.onPauseStart.listen(_deletePauseEvents);
    events.onPauseExit.listen(_deletePauseEvents);
    events.onPauseBreakpoint.listen(_deletePauseEvents);
    events.onPauseInterrupted.listen(_deletePauseEvents);
    events.onPauseException.listen(_deletePauseEvents);

    // show notification for an event.
    events.onIsolateReload.listen(_addNotification);
    events.onPauseExit.listen(_addNotification);
    events.onPauseBreakpoint.listen(_addNotification);
    events.onPauseInterrupted.listen(_addNotification);
    events.onPauseException.listen(_addNotification);
    events.onInspect.listen(_addNotification);
    events.onConnectionClosed.listen(_addNotification);
  }

  void handleException(e, st) {
    if (e is ServerRpcException) {
      if (e.code == ServerRpcException.kFeatureDisabled) return;
      if (e.code == ServerRpcException.kIsolateMustBePaused) return;
      if (e.code == ServerRpcException.kCannotAddBreakpoint) return;
      Logger.root.fine('Dropping exception: ${e}\n${st}');
    }

    // TODO(turnidge): Report this failure via analytics.
    Logger.root.warning('Caught exception: ${e}\n${st}');
    notifications.add(new ExceptionNotification(e, stacktrace: st));
  }

  // This map keeps track of which curly-blocks have been expanded by the user.
  Map<String, bool> expansions = {};
}
