// Copyright (c) 2016, 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:convert';
import 'dart:io';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:unittest/unittest.dart';

import '../../test/integration/integration_tests.dart';

void printMemoryResults(String id, String description, List<int> sizes) {
  String now = new DateTime.now().toUtc().toIso8601String();
  print('$now ========== $id');
  print('memory: $sizes');
  print(description.trim());
  print('--------------------');
  print('');
  print('');
}

/**
 * Base class for analysis server memory usage tests.
 */
class AnalysisServerMemoryUsageTest
    extends AbstractAnalysisServerIntegrationTest {
  static const int vmServicePort = 12345;

  int getMemoryUsage() {
    ProcessResult result = _run('curl', <String>[
      'localhost:$vmServicePort/_getAllocationProfile\?isolateId=isolates/root\&gc=full'
    ]);
    Map json = JSON.decode(result.stdout);
    Map heaps = json['result']['heaps'];
    int newSpace = heaps['new']['used'];
    int oldSpace = heaps['old']['used'];
    return newSpace + oldSpace;
  }

  /**
   * Send the server an 'analysis.setAnalysisRoots' command directing it to
   * analyze [sourceDirectory].
   */
  Future setAnalysisRoot() =>
      sendAnalysisSetAnalysisRoots([sourceDirectory.path], []);

  /**
   * The server is automatically started before every test.
   */
  @override
  Future setUp() {
    onAnalysisErrors.listen((AnalysisErrorsParams params) {
      currentAnalysisErrors[params.file] = params.errors;
    });
    onServerError.listen((ServerErrorParams params) {
      // A server error should never happen during an integration test.
      fail('${params.message}\n${params.stackTrace}');
    });
    Completer serverConnected = new Completer();
    onServerConnected.listen((_) {
      expect(serverConnected.isCompleted, isFalse);
      serverConnected.complete();
    });
    return startServer(servicesPort: vmServicePort).then((_) {
      server.listenToOutput(dispatchNotification);
      server.exitCode.then((_) {
        skipShutdown = true;
      });
      return serverConnected.future;
    });
  }

  /**
   * After every test, the server is stopped.
   */
  Future shutdown() async => await shutdownIfNeeded();

  /**
   * Enable [ServerService.STATUS] notifications so that [analysisFinished]
   * can be used.
   */
  Future subscribeToStatusNotifications() async {
    await sendServerSetSubscriptions([ServerService.STATUS]);
  }

  /**
   * Synchronously run the given [executable] with the given [arguments]. Return
   * the result of running the process.
   */
  ProcessResult _run(String executable, List<String> arguments) {
    return Process.runSync(executable, arguments,
        stderrEncoding: UTF8, stdoutEncoding: UTF8);
  }

  /**
   *  1. Start Analysis Server.
   *  2. Set the analysis [roots].
   *  3. Wait for analysis to complete.
   *  4. Record the time to finish analysis.
   *  5. Shutdown.
   *  6. Go to (1).
   */
  static Future<List<int>> start_waitInitialAnalysis_shutdown(
      {List<String> roots, int numOfRepeats}) async {
    expect(roots, isNotNull, reason: 'roots');
    expect(numOfRepeats, isNotNull, reason: 'numOfRepeats');
    // Repeat.
    List<int> sizes = <int>[];
    for (int i = 0; i < numOfRepeats; i++) {
      AnalysisServerMemoryUsageTest test = new AnalysisServerMemoryUsageTest();
      // Initialize Analysis Server.
      await test.setUp();
      await test.subscribeToStatusNotifications();
      // Set roots and analyze.
      await test.sendAnalysisSetAnalysisRoots(roots, []);
      await test.analysisFinished;
      sizes.add(test.getMemoryUsage());
      // Stop the server.
      await test.shutdown();
    }
    return sizes;
  }
}
