// 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 'dart:math';

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) {
  int minMemory = sizes.fold(sizes.first, min);
  int maxMemory = sizes.fold(sizes.first, max);
  String now = new DateTime.now().toUtc().toIso8601String();
  print('$now ========== $id');
  print('memory: $sizes');
  print('min_memory: $minMemory');
  print('max_memory: $maxMemory');
  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 heap size after analysis is finished.
   *  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;
  }
}
