// 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 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();

    await test.openFile(filePath, contents);
    await test.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());
  static final lsp = ServerBenchmark('lsp-analysis-server',
      'LSP Analysis Server', () => LspAnalysisServerBenchmarkTest());
  final String id;

  final String name;
  final AbstractBenchmarkTest Function() testConstructor;

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