// 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:path/path.dart' as path;

import '../benchmarks.dart';
import 'memory_tests.dart';

/// benchmarks:
///   - analysis-server-warm-analysis
///   - analysis-server-warm-memory
///   - analysis-server-edit
///   - analysis-server-completion
class AnalysisBenchmark extends Benchmark {
  final AbstractBenchmarkTest Function() testConstructor;

  AnalysisBenchmark(ServerBenchmark benchmarkTest)
      : testConstructor = benchmarkTest.testConstructor,
        super(
            benchmarkTest.id,
            '${benchmarkTest.name} benchmarks of a large project, with an existing '
            'driver cache.',
            kind: 'group');

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

    var test = testConstructor();
    if (verbose) {
      test.debugStdio();
    }
    await test.setUp(dartSdkPath, getProjectRoots(quick: quick));
    await test.analysisFinished;

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

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

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

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

    await test.shutdown();

    return result;
  }

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

    var filePath =
        path.join(analysisServerSrcPath, 'lib', 'src', 'analysis_server.dart');
    var contents = File(filePath).readAsStringSync();

    await test.openFile(filePath, contents);

    var completionCount = 0;
    var stopwatch = Stopwatch()..start();

    Future<void> complete(int offset) async {
      await test.complete(filePath, offset, isWarmUp: false);
      completionCount++;
    }

    for (var i = 0; i < kGroupCount; i++) {
      var startIndex = i * (contents.length ~/ (kGroupCount + 2));
      // Look for a line with a period in it that ends with a semi-colon.
      var index =
          contents.indexOf(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.updateFile(filePath, contents);
      }
    }

    stopwatch.stop();

    await test.closeFile(filePath);

    return stopwatch.elapsedMicroseconds ~/ completionCount;
  }

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

    var filePath =
        path.join(analysisServerSrcPath, 'lib', 'src', 'analysis_server.dart');
    var contents = File(filePath).readAsStringSync();

    // Get the future for `analysisFinished` *before* the call to [openFile]
    // as the analysis triggered by opening is sometimes so fast that it
    // finishes before starting to listen if only starting *after* the call to
    // [openFile].
    Future<void> analysisFinished = test.analysisFinished;
    await test.openFile(filePath, contents);
    await analysisFinished;

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

    for (var i = 0; i < kGroupCount; i++) {
      var startIndex = i * (contents.length ~/ (kGroupCount + 2));
      var index = contents.indexOf(';', startIndex);
      contents =
          '${contents.substring(0, index + 1)} ${contents.substring(index + 1)}';
      await test.updateFile(filePath, contents);
      await test.analysisFinished;
    }

    stopwatch.stop();

    await test.closeFile(filePath);

    return stopwatch.elapsedMicroseconds ~/ kGroupCount;
  }
}

/// benchmarks:
///   - analysis-server-cold-analysis
///   - analysis-server-cold-memory
class ColdAnalysisBenchmark extends Benchmark {
  final AbstractBenchmarkTest Function() testConstructor;

  ColdAnalysisBenchmark(ServerBenchmark benchmarkTest)
      : testConstructor = benchmarkTest.testConstructor,
        super(
            '${benchmarkTest.id}-cold',
            '${benchmarkTest.name} benchmarks of a large project on start-up, no '
                'existing driver cache.',
            kind: 'group');

  @override
  int get maxIterations => 3;

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

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

    var test = testConstructor();
    await test.setUp(dartSdkPath, getProjectRoots(quick: quick));
    await test.analysisFinished;

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

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

    await test.shutdown();

    return result;
  }
}

class ServerBenchmark {
  static final das = ServerBenchmark(
      'analysis-server', 'Analysis Server', AnalysisServerBenchmarkTest.new);
  static final lsp = ServerBenchmark('lsp-analysis-server',
      'LSP Analysis Server', LspAnalysisServerBenchmarkTest.new);
  final String id;

  final String name;
  final AbstractBenchmarkTest Function() testConstructor;

  ServerBenchmark(this.id, this.name, this.testConstructor);
}
