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

import 'package:path/path.dart' as path;
import 'package:test/test.dart';

final dartCompile = () {
  final sdkBin = path.dirname(Platform.executable);
  final dartCmd = path.join(sdkBin, Platform.isWindows ? 'dart.exe' : 'dart');

  if (!File(dartCmd).existsSync()) {
    throw 'Failed to locate `dart` in the SDK';
  }

  return path.canonicalize(dartCmd);
}();

class AotSnapshot {
  final String outputBinary;
  final String sizesJson;

  AotSnapshot({required this.outputBinary, required this.sizesJson});
}

Future withFlag(
    Map<String, String> source, String flag, Future Function(String) f) {
  return withFlagImpl(source, flag, (info) => f(info.sizesJson));
}

Future withFlagImpl(
    Map<String, String> source, String? flag, Future Function(AotSnapshot) f) {
  return withTempDir((dir) async {
    final snapshot = AotSnapshot(
      outputBinary: path.join(dir, 'output.exe'),
      sizesJson: path.join(dir, 'sizes.json'),
    );
    final packages = path.join(dir, '.packages');
    final mainDart = path.join(dir, 'main.dart');

    // Create test input.
    for (var file in source.entries) {
      await File(path.join(dir, file.key)).writeAsString(file.value);
    }
    await File(packages).writeAsString('''
{
  "configVersion": 2,
  "packages": [
    {
      "name": "input",
      "rootUri": "./"
    }
  ]
}
''');
    await File(mainDart).writeAsString('''
import 'package:input/input.dart' as input;

void main(List<String> args) => input.main(args);
''');

    final extraGenSnapshotOptions = [
      '--dwarf-stack-traces',
      if (flag != null) '$flag=${snapshot.sizesJson}',
    ];

    final args = [
      'compile',
      'exe',
      '-o',
      snapshot.outputBinary,
      '--packages=$packages',
      '--extra-gen-snapshot-options=${extraGenSnapshotOptions.join(',')}',
      mainDart,
    ];

    // Compile input.dart to native and output instruction sizes.
    final result = await Process.run(dartCompile, args);

    expect(result.exitCode, equals(0), reason: '''
Compilation completed with exit code ${result.exitCode}.

Command line: $dartCompile ${args.join(' ')}

stdout: ${result.stdout}
stderr: ${result.stderr}
''');
    expect(File(snapshot.outputBinary).existsSync(), isTrue,
        reason: 'Output binary exists');
    if (flag != null) {
      expect(File(snapshot.sizesJson).existsSync(), isTrue,
          reason: 'Instruction sizes output exists');
    }

    await f(snapshot);
  });
}

final shouldKeepTemporaryDirectories =
    Platform.environment['KEEP_TEMPORARY_DIRECTORIES']?.isNotEmpty == true;

Future withTempDir(Future Function(String dir) f) async {
  final tempDir =
      Directory.systemTemp.createTempSync('instruction-sizes-test-');
  try {
    await f(tempDir.path);
  } finally {
    if (shouldKeepTemporaryDirectories) {
      tempDir.deleteSync(recursive: true);
    }
  }
}

Future<Object> loadJson(File input) async {
  return (await input
      .openRead()
      .transform(utf8.decoder)
      .transform(json.decoder)
      .first)!;
}
