// Copyright (c) 2017, 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.

import 'dart:async';
import 'dart:io';

import 'package:analysis_server/src/protocol_server.dart';
import 'package:path/path.dart' as path;

import '../../test/integration/support/integration_tests.dart';
import '../benchmarks.dart';
import 'memory_tests.dart';

/// benchmarks:
///   - analysis-server-cold-analysis
///   - analysis-server-cold-memory
class ColdAnalysisBenchmark extends Benchmark {
  ColdAnalysisBenchmark()
      : super(
            'analysis-server-cold',
            'Analysis server benchmarks of a large project on start-up, no '
            'existing driver cache.',
            kind: 'group');

  int get maxIterations => 3;

  @override
  Future<BenchMarkResult> run({
    bool quick = false,
    bool verbose = false,
  }) async {
    if (!quick) {
      deleteServerCache();
    }

    Stopwatch stopwatch = new Stopwatch()..start();

    AnalysisServerMemoryUsageTest test = new AnalysisServerMemoryUsageTest();
    await test.setUp();
    await test.subscribeToStatusNotifications();
    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []);
    await test.analysisFinished;

    stopwatch.stop();
    int usedBytes = await test.getMemoryUsage();

    CompoundBenchMarkResult result = new CompoundBenchMarkResult(id);
    result.add('analysis',
        new BenchMarkResult('micros', stopwatch.elapsedMicroseconds));
    result.add('memory', new BenchMarkResult('bytes', usedBytes));

    await test.shutdown();

    return result;
  }
}

/// benchmarks:
///   - analysis-server-warm-analysis
///   - analysis-server-warm-memory
///   - analysis-server-edit
///   - analysis-server-completion
class AnalysisBenchmark extends Benchmark {
  AnalysisBenchmark()
      : super(
            'analysis-server',
            'Analysis server benchmarks of a large project, with an existing '
            'driver cache.',
            kind: 'group');

  @override
  Future<BenchMarkResult> run({
    bool quick = false,
    bool verbose = false,
  }) async {
    Stopwatch stopwatch = new Stopwatch()..start();

    AnalysisServerMemoryUsageTest test = new AnalysisServerMemoryUsageTest();
    if (verbose) {
      test.debugStdio();
    }
    await test.setUp();
    await test.subscribeToStatusNotifications();
    await test.sendAnalysisSetAnalysisRoots(getProjectRoots(quick: quick), []);
    await test.analysisFinished;

    stopwatch.stop();
    int usedBytes = await test.getMemoryUsage();

    CompoundBenchMarkResult result = new CompoundBenchMarkResult(id);
    result.add('warm-analysis',
        new BenchMarkResult('micros', stopwatch.elapsedMicroseconds));
    result.add('warm-memory', new BenchMarkResult('bytes', usedBytes));

    if (!quick) {
      // change timing
      final int editMicros = await _calcEditTiming(test);
      result.add('edit', new BenchMarkResult('micros', editMicros));

      // code completion
      final int completionMicros = await _calcCompletionTiming(test);
      result.add('completion', new BenchMarkResult('micros', completionMicros));
    }

    await test.shutdown();

    return result;
  }

  Future<int> _calcEditTiming(
      AbstractAnalysisServerIntegrationTest test) async {
    const int kGroupCount = 5;

    final String filePath =
        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart');
    String contents = new File(filePath).readAsStringSync();

    await test
        .sendAnalysisUpdateContent({filePath: new AddContentOverlay(contents)});

    final Stopwatch stopwatch = new Stopwatch()..start();

    for (int i = 0; i < kGroupCount; i++) {
      int startIndex = i * (contents.length ~/ (kGroupCount + 2));
      int index = contents.indexOf(';', startIndex);
      contents = contents.substring(0, index + 1) +
          ' ' +
          contents.substring(index + 1);
      await test.sendAnalysisUpdateContent(
          {filePath: new AddContentOverlay(contents)});
      await test.analysisFinished;
    }

    stopwatch.stop();

    return stopwatch.elapsedMicroseconds ~/ kGroupCount;
  }

  Future<int> _calcCompletionTiming(
      AbstractAnalysisServerIntegrationTest test) async {
    const int kGroupCount = 10;

    final String filePath =
        path.join(analysisServerSrcPath, 'lib/src/analysis_server.dart');
    String contents = new File(filePath).readAsStringSync();

    await test
        .sendAnalysisUpdateContent({filePath: new AddContentOverlay(contents)});

    int completionCount = 0;
    final Stopwatch stopwatch = new Stopwatch()..start();

    Future _complete(int offset) async {
      // Create a new non-broadcast stream and subscribe to
      // test.onCompletionResults before sending a request.
      // Otherwise we could skip results which where posted to
      // test.onCompletionResults after request is sent but
      // before subscribing to test.onCompletionResults.
      final completionResults = new StreamController<CompletionResultsParams>();
      completionResults.sink.addStream(test.onCompletionResults);

      CompletionGetSuggestionsResult result =
          await test.sendCompletionGetSuggestions(filePath, offset);

      Future<CompletionResultsParams> future = completionResults.stream
          .where((CompletionResultsParams params) =>
              params.id == result.id && params.isLast)
          .first;
      await future;

      completionCount++;
    }

    for (int i = 0; i < kGroupCount; i++) {
      int startIndex = i * (contents.length ~/ (kGroupCount + 2));
      // Look for a line with a period in it that ends with a semi-colon.
      int index =
          contents.indexOf(new RegExp(r'\..*;$', multiLine: true), startIndex);

      await _complete(index - 10);
      await _complete(index - 1);
      await _complete(index);
      await _complete(index + 1);
      await _complete(index + 10);

      if (i + 1 < kGroupCount) {
        // mutate
        index = contents.indexOf(';', index);
        contents = contents.substring(0, index + 1) +
            ' ' +
            contents.substring(index + 1);
        await test.sendAnalysisUpdateContent(
            {filePath: new AddContentOverlay(contents)});
      }
    }

    stopwatch.stop();

    return stopwatch.elapsedMicroseconds ~/ completionCount;
  }
}
