// 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.

// @dart = 2.8

import 'dart:async';

import 'package:meta/meta.dart';
import 'package:vm_service/vm_service.dart' as vm_service;

import 'base/common.dart';
import 'base/error_handling_io.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/utils.dart';
import 'vmservice.dart';

// Names of some of the Timeline events we care about.
const String kFlutterEngineMainEnterEventName = 'FlutterEngineMainEnter';
const String kFrameworkInitEventName = 'Framework initialization';
const String kFirstFrameBuiltEventName = 'Widgets built first useful frame';
const String kFirstFrameRasterizedEventName = 'Rasterized first useful frame';

class Tracing {
  Tracing({
    @required this.vmService,
    @required Logger logger,
  }) : _logger = logger;

  static const String firstUsefulFrameEventName = kFirstFrameRasterizedEventName;

  final vm_service.VmService vmService;
  final Logger _logger;

  Future<void> startTracing() async {
    await vmService.setTimelineFlags(<String>['Compiler', 'Dart', 'Embedder', 'GC']);
    await vmService.clearVMTimeline();
  }

  /// Stops tracing; optionally wait for first frame.
  Future<Map<String, dynamic>> stopTracingAndDownloadTimeline({
    bool awaitFirstFrame = false,
  }) async {
    if (awaitFirstFrame) {
      final Status status = _logger.startProgress(
        'Waiting for application to render first frame...',
      );
      try {
        final Completer<void> whenFirstFrameRendered = Completer<void>();
        try {
          await vmService.streamListen(vm_service.EventStreams.kExtension);
        } on vm_service.RPCError {
          // It is safe to ignore this error because we expect an error to be
          // thrown if we're already subscribed.
        }
        vmService.onExtensionEvent.listen((vm_service.Event event) {
          if (event.extensionKind == 'Flutter.FirstFrame') {
            whenFirstFrameRendered.complete();
          }
        });
        bool done = false;
        final List<FlutterView> views = await vmService.getFlutterViews();
        for (final FlutterView view in views) {
          if (await vmService
              .flutterAlreadyPaintedFirstUsefulFrame(
                isolateId: view.uiIsolate.id,
              )) {
            done = true;
            break;
          }
        }
        if (!done) {
          await whenFirstFrameRendered.future;
        }
      // The exception is rethrown, so don't catch only Exceptions.
      } catch (exception) { // ignore: avoid_catches_without_on_clauses
        status.cancel();
        rethrow;
      }
      status.stop();
    }
    final vm_service.Response timeline = await vmService.getTimeline();
    await vmService.setTimelineFlags(<String>[]);
    if (timeline == null) {
      throwToolExit(
        'The device disconnected before the timeline could be retrieved.',
      );
    }
    return timeline.json;
  }
}

/// Download the startup trace information from the given observatory client and
/// store it to build/start_up_info.json.
Future<void> downloadStartupTrace(vm_service.VmService vmService, {
  bool awaitFirstFrame = true,
  @required Logger logger,
  @required Directory output,
}) async {
  final File traceInfoFile = output.childFile('start_up_info.json');

  // Delete old startup data, if any.
  ErrorHandlingFileSystem.deleteIfExists(traceInfoFile);

  // Create "build" directory, if missing.
  if (!traceInfoFile.parent.existsSync()) {
    traceInfoFile.parent.createSync();
  }

  final Tracing tracing = Tracing(vmService: vmService, logger: logger);

  final Map<String, dynamic> timeline = await tracing.stopTracingAndDownloadTimeline(
    awaitFirstFrame: awaitFirstFrame,
  );

  final File traceTimelineFile = output.childFile('start_up_timeline.json');
  traceTimelineFile.writeAsStringSync(toPrettyJson(timeline));

  int extractInstantEventTimestamp(String eventName) {
    final List<Map<String, dynamic>> events =
        List<Map<String, dynamic>>.from(timeline['traceEvents'] as List<dynamic>);
    final Map<String, dynamic> event = events.firstWhere(
      (Map<String, dynamic> event) => event['name'] == eventName, orElse: () => null,
    );
    return event == null ? null : (event['ts'] as int);
  }

  String message = 'No useful metrics were gathered.';

  final int engineEnterTimestampMicros = extractInstantEventTimestamp(kFlutterEngineMainEnterEventName);
  final int frameworkInitTimestampMicros = extractInstantEventTimestamp(kFrameworkInitEventName);

  if (engineEnterTimestampMicros == null) {
    logger.printTrace('Engine start event is missing in the timeline: $timeline');
    throwToolExit('Engine start event is missing in the timeline. Cannot compute startup time.');
  }

  final Map<String, dynamic> traceInfo = <String, dynamic>{
    'engineEnterTimestampMicros': engineEnterTimestampMicros,
  };

  if (frameworkInitTimestampMicros != null) {
    final int timeToFrameworkInitMicros = frameworkInitTimestampMicros - engineEnterTimestampMicros;
    traceInfo['timeToFrameworkInitMicros'] = timeToFrameworkInitMicros;
    message = 'Time to framework init: ${timeToFrameworkInitMicros ~/ 1000}ms.';
  }

  if (awaitFirstFrame) {
    final int firstFrameBuiltTimestampMicros = extractInstantEventTimestamp(kFirstFrameBuiltEventName);
    final int firstFrameRasterizedTimestampMicros = extractInstantEventTimestamp(kFirstFrameRasterizedEventName);
    if (firstFrameBuiltTimestampMicros == null || firstFrameRasterizedTimestampMicros == null) {
      logger.printTrace('First frame events are missing in the timeline: $timeline');
      throwToolExit('First frame events are missing in the timeline. Cannot compute startup time.');
    }

    // To keep our old benchmarks valid, we'll preserve the
    // timeToFirstFrameMicros as the firstFrameBuiltTimestampMicros.
    // Additionally, we add timeToFirstFrameRasterizedMicros for a more accurate
    // benchmark.
    traceInfo['timeToFirstFrameRasterizedMicros'] = firstFrameRasterizedTimestampMicros - engineEnterTimestampMicros;
    final int timeToFirstFrameMicros = firstFrameBuiltTimestampMicros - engineEnterTimestampMicros;
    traceInfo['timeToFirstFrameMicros'] = timeToFirstFrameMicros;
    message = 'Time to first frame: ${timeToFirstFrameMicros ~/ 1000}ms.';
    if (frameworkInitTimestampMicros != null) {
      traceInfo['timeAfterFrameworkInitMicros'] = firstFrameBuiltTimestampMicros - frameworkInitTimestampMicros;
    }
  }

  traceInfoFile.writeAsStringSync(toPrettyJson(traceInfo));

  logger.printStatus(message);
  logger.printStatus('Saved startup trace info in ${traceInfoFile.path}.');
}
