// 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:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:args/command_runner.dart';
import 'package:intl/intl.dart';
import 'package:path/path.dart' as path;

import 'perf/benchmarks_impl.dart';
import 'perf/flutter_analyze_benchmark.dart';

Future main(List<String> args) async {
  final List<Benchmark> benchmarks = [
    new ColdAnalysisBenchmark(),
    new AnalysisBenchmark(),
    new FlutterAnalyzeBenchmark(),
  ];

  CommandRunner runner = new CommandRunner(
      'benchmark', 'A benchmark runner for the analysis server.');
  runner.addCommand(new ListCommand(benchmarks));
  runner.addCommand(new RunCommand(benchmarks));
  runner.run(args);
}

class ListCommand extends Command {
  final List<Benchmark> benchmarks;

  ListCommand(this.benchmarks) {
    argParser.addFlag('machine',
        negatable: false, help: 'Emit the list of benchmarks as json.');
  }

  @override
  String get name => 'list';

  @override
  String get description => 'List available benchmarks.';

  @override
  String get invocation => '${runner.executableName} $name';

  void run() {
    if (argResults['machine'] as bool) {
      final Map map = {
        'benchmarks': benchmarks.map((b) => b.toJson()).toList()
      };
      print(new JsonEncoder.withIndent('  ').convert(map));
    } else {
      for (Benchmark benchmark in benchmarks) {
        print('${benchmark.id}: ${benchmark.description}');
      }
    }
  }
}

class RunCommand extends Command {
  final List<Benchmark> benchmarks;

  RunCommand(this.benchmarks) {
    argParser.addFlag('quick',
        negatable: false,
        help: 'Run a quick version of the benchmark. This is not useful for '
            'gathering accurate times,\nbut can be used to validate that the '
            'benchmark works.');
    argParser.addFlag('use-cfe',
        negatable: false,
        help: 'Benchmark against the Dart 2.0 front end implementation.');
    argParser.addOption('repeat',
        defaultsTo: '10', help: 'The number of times to repeat the benchmark.');
    argParser.addFlag('verbose',
        negatable: false,
        help: 'Print all communication to and from the analysis server.');
  }

  @override
  String get name => 'run';

  @override
  String get description => 'Run a given benchmark.';

  @override
  String get invocation => '${runner.executableName} $name <benchmark-id>';

  Future run() async {
    if (argResults.rest.isEmpty) {
      printUsage();
      exit(1);
    }

    final String benchmarkId = argResults.rest.first;
    final int repeatCount = int.parse(argResults['repeat'] as String);
    final bool quick = argResults['quick'];
    final bool useCFE = argResults['use-cfe'];
    final bool verbose = argResults['verbose'];

    final Benchmark benchmark =
        benchmarks.firstWhere((b) => b.id == benchmarkId, orElse: () {
      print("Benchmark '$benchmarkId' not found.");
      exit(1);
      // Never reached.
      return null;
    });

    int actualIterations = repeatCount;
    if (benchmark.maxIterations > 0) {
      actualIterations = math.min(benchmark.maxIterations, repeatCount);
    }

    if (benchmark.needsSetup) {
      print('Setting up $benchmarkId...');
      await benchmark.oneTimeSetup();
    }

    try {
      BenchMarkResult result;
      Stopwatch time = new Stopwatch()..start();
      print('Running $benchmarkId $actualIterations times...');

      for (int iteration = 0; iteration < actualIterations; iteration++) {
        BenchMarkResult newResult = await benchmark.run(
          quick: quick,
          useCFE: useCFE,
          verbose: verbose,
        );
        print('  $newResult');
        result = result == null ? newResult : result.combine(newResult);
      }

      time.stop();
      print('Finished in ${time.elapsed.inSeconds} seconds.\n');
      Map m = {'benchmark': benchmarkId, 'result': result.toJson()};
      print(json.encode(m));

      await benchmark.oneTimeCleanup();
    } catch (error, st) {
      print('$benchmarkId threw exception: $error');
      print(st);
      exit(1);
    }
  }
}

abstract class Benchmark {
  final String id;
  final String description;
  final bool enabled;

  /// One of 'memory', 'cpu', or 'group'.
  final String kind;

  Benchmark(this.id, this.description, {this.enabled: true, this.kind: 'cpu'});

  bool get needsSetup => false;

  Future oneTimeSetup() => new Future.value();

  Future oneTimeCleanup() => new Future.value();

  Future<BenchMarkResult> run({
    bool quick: false,
    bool useCFE: false,
    bool verbose: false,
  });

  int get maxIterations => 0;

  Map toJson() =>
      {'id': id, 'description': description, 'enabled': enabled, 'kind': kind};

  String toString() => '$id: $description';
}

class BenchMarkResult {
  static final NumberFormat nf = new NumberFormat.decimalPattern();

  /// One of 'bytes', 'micros', or 'compound'.
  final String kindName;

  final int value;

  BenchMarkResult(this.kindName, this.value);

  BenchMarkResult combine(BenchMarkResult other) {
    return new BenchMarkResult(kindName, math.min(value, other.value));
  }

  Map toJson() => {kindName: value};

  String toString() => '$kindName: ${nf.format(value)}';
}

class CompoundBenchMarkResult extends BenchMarkResult {
  final String name;

  CompoundBenchMarkResult(this.name) : super('compound', 0);

  Map<String, BenchMarkResult> results = {};

  void add(String name, BenchMarkResult result) {
    results[name] = result;
  }

  BenchMarkResult combine(BenchMarkResult other) {
    BenchMarkResult _combine(BenchMarkResult a, BenchMarkResult b) {
      if (a == null) return b;
      if (b == null) return a;
      return a.combine(b);
    }

    CompoundBenchMarkResult o = other as CompoundBenchMarkResult;

    CompoundBenchMarkResult combined = new CompoundBenchMarkResult(name);
    List<String> keys = (new Set<String>()
          ..addAll(results.keys)
          ..addAll(o.results.keys))
        .toList();

    for (String key in keys) {
      combined.add(key, _combine(results[key], o.results[key]));
    }

    return combined;
  }

  Map toJson() {
    Map m = {};
    for (String key in results.keys) {
      m['$name-$key'] = results[key].toJson();
    }
    return m;
  }

  String toString() => '${toJson()}';
}

List<String> getProjectRoots({bool quick: false}) {
  String script = Platform.script.toFilePath(windows: Platform.isWindows);
  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
  return <String>[path.join(pkgPath, quick ? 'meta' : 'analysis_server')];
}

String get analysisServerSrcPath {
  String script = Platform.script.toFilePath(windows: Platform.isWindows);
  String pkgPath = path.normalize(path.join(path.dirname(script), '..', '..'));
  return path.join(pkgPath, 'analysis_server');
}

void deleteServerCache() {
  // ~/.dartServer/.analysis-driver/
  ResourceProvider resourceProvider = PhysicalResourceProvider.INSTANCE;
  Folder stateLocation = resourceProvider.getStateLocation('.analysis-driver');
  try {
    if (stateLocation.exists) {
      stateLocation.delete();
    }
  } catch (e) {
    // ignore any exception
  }
}
