// 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.

// This script generates the
// lib/src/front_end/resources/resources.g.dart file from the contents
// of the lib/src/front_end/resources directory.

import 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:args/args.dart';
import 'package:crypto/crypto.dart';
import 'package:path/path.dart' as path;

void main(List<String> args) async {
  var argParser = ArgParser()
    ..addFlag('verify', negatable: false)
    ..addFlag('dev', negatable: false)
    ..addFlag('help', negatable: false);
  var argResults = argParser.parse(args);
  if (argResults['help'] == true) {
    fail('''
usage: dart pkg/nnbd_migration/tool/codegen/generate_resources.dart [--verify]

Run with no args to generate web resources for the NNBD migration preview tool.
Run with '--verify' to validate that the web resource have been regenerated.
''');
  }

  if (FileSystemEntity.isFileSync(
      path.join('tool', 'codegen', 'generate_resources.dart'))) {
    // We're running from the project root - cd up two directories.
    Directory.current = Directory.current.parent.parent;
  } else if (!FileSystemEntity.isDirectorySync(
      path.join('pkg', 'nnbd_migration'))) {
    fail('Please run this tool from the root of the sdk repo.');
  }

  bool verify = argResults['verify'] as bool;
  bool dev = argResults['dev'] as bool;

  if (verify) {
    verifyResourcesGDartGenerated();
  } else {
    await compileWebFrontEnd(devMode: dev);

    print('');

    createResourcesGDart();
  }
}

final File dartSources = File(path.join('pkg', 'nnbd_migration', 'lib', 'src',
    'front_end', 'web', 'migration.dart'));

final javascriptOutput = File(path.join('pkg', 'nnbd_migration', 'lib', 'src',
    'front_end', 'resources', 'migration.js'));

final Directory resourceDir = Directory(
    path.join('pkg', 'nnbd_migration', 'lib', 'src', 'front_end', 'resources'));

final File resourcesFile = File(path.join('pkg', 'nnbd_migration', 'lib', 'src',
    'front_end', 'resources', 'resources.g.dart'));

final List<String> resourceTypes = [
  '.css',
  '.html',
  '.js',
];

String base64Encode(List<int> bytes) {
  var encoded = base64.encode(bytes);

  // Logic to cut lines into 80-character chunks.
  var lines = <String>[];
  var index = 0;

  while (index < encoded.length) {
    var line = encoded.substring(index, math.min(index + 80, encoded.length));
    lines.add(line);
    index += line.length;
  }

  return lines.join('\n');
}

void compileWebFrontEnd({bool devMode = false}) async {
  var sdkBinDir = path.dirname(Platform.resolvedExecutable);
  var dart2jsPath = path.join(sdkBinDir, 'dart2js');

  // dart2js -m -o output source
  var process = await Process.start(dart2jsPath, [
    devMode ? '-O1' : '-m',
    '--no-frequency-based-minification',
    '-o',
    javascriptOutput.path,
    dartSources.path,
  ]);
  process.stdout.listen((List<int> data) => stdout.add(data));
  process.stderr.listen((List<int> data) => stderr.add(data));
  var exitCode = await process.exitCode;

  if (exitCode != 0) {
    fail('Failed compiling ${dartSources.path}.');
  }
}

void createResourcesGDart() {
  var content =
      generateResourceFile(sortDir(resourceDir.listSync()).where((entity) {
    var name = path.basename(entity.path);
    return entity is File && resourceTypes.contains(path.extension(name));
  }).cast<File>());

  // write the content
  resourcesFile.writeAsStringSync(content);
}

void fail(String message) {
  stderr.writeln(message);
  exit(1);
}

/// Fail the script, and print out a message indicating how to regenerate the
/// resources file.
void failGenerate(String message) {
  stderr.writeln('$message.');
  stderr.writeln();
  stderr.writeln('''
To re-generate lib/src/front_end/resources/resources.g.dart, run:

  dart pkg/nnbd_migration/tool/codegen/generate_resources.dart
''');
  exit(1);
}

String generateResourceFile(Iterable<File> resources) {
  var filePath = path.relative(Platform.script.toFilePath());
  var buf = StringBuffer('''
// 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.

// This file is generated; don't edit it directly.
//
// See $filePath for how
// to edit the source content and for re-generation instructions.

import 'dart:convert' as convert;
''');

  for (var resource in resources) {
    var name = path.basename(resource.path).replaceAll('.', '_');
    print('adding $name...');

    buf.writeln();
    buf.writeln('String get $name {');
    buf.writeln('  return _$name ??= _decode(_${name}_base64);');
    buf.writeln('}');
  }

  buf.writeln(r'''

String _decode(String data) {
  data = data.replaceAll('\n', '').trim();
  return String.fromCharCodes(convert.base64Decode(data));
}''');

  for (var resource in resources) {
    var name = path.basename(resource.path).replaceAll('.', '_');
    var source = resource.readAsStringSync();

    var delimiter = "'''";

    buf.writeln();
    buf.writeln('String _$name;');
    if (name == path.basename(javascriptOutput.path).replaceAll('.', '_')) {
      // Write out the crc for the dart code.
      var sourceCode = StringBuffer();
      // collect the dart source code
      for (var entity in sortDir(dartSources.parent.listSync())) {
        if (entity.path.endsWith('.dart')) {
          sourceCode.write((entity as File).readAsStringSync());
        }
      }
      buf.writeln(
          "// migration_dart md5 is '${md5String(sourceCode.toString())}'");
    } else {
      // highlight_css md5 is 'fb012626bafd286510d32da815dae448'
      buf.writeln("// $name md5 is '${md5String(source)}'");
    }
    buf.writeln('String _${name}_base64 = $delimiter');
    buf.writeln(base64Encode(source.codeUnits));
    buf.writeln('$delimiter;');
  }

  return buf.toString();
}

String md5String(String str) {
  return md5.convert(str.codeUnits).toString();
}

List<FileSystemEntity> sortDir(Iterable<FileSystemEntity> entities) {
  var result = entities.toList();
  result.sort((a, b) => a.path.compareTo(b.path));
  return result;
}

void verifyResourcesGDartGenerated({
  VerificationFunction failVerification = failGenerate,
}) {
  print('Verifying that ${path.basename(resourcesFile.path)} is up-to-date...');

  // Find the hashes for the last generated version of resources.g.dart.
  var resourceHashes = <String, String>{};
  // highlight_css md5 is 'fb012626bafd286510d32da815dae448'
  var hashPattern = RegExp(r"// (\S+) md5 is '(\S+)'");
  for (var match in hashPattern.allMatches(resourcesFile.readAsStringSync())) {
    resourceHashes[match.group(1)] = match.group(2);
  }

  // For all resources (modulo compiled JS ones), verify the hash.
  for (var entity in sortDir(resourceDir.listSync())) {
    var name = path.basename(entity.path);
    if (!resourceTypes.contains(path.extension(name))) {
      continue;
    }

    if (name == 'migration.js') {
      // skip the compiled js
      continue;
    }

    var key = name.replaceAll('.', '_');
    if (!resourceHashes.containsKey(key)) {
      failVerification('No entry on resources.g.dart for $name');
    } else {
      var hash = md5String((entity as File).readAsStringSync());
      if (hash != resourceHashes[key]) {
        failVerification('$name not up to date in resources.g.dart');
      }
    }
  }

  // verify the compiled dart code
  var sourceCode = StringBuffer();
  for (var entity in sortDir(dartSources.parent.listSync())) {
    if (entity.path.endsWith('.dart')) {
      sourceCode.write((entity as File).readAsStringSync());
    }
  }
  var hash = md5String(sourceCode.toString());
  if (hash != resourceHashes['migration_dart']) {
    failVerification('Compiled javascript not up to date in resources.g.dart');
  }

  print('Generated resources up to date.');
}

typedef VerificationFunction = void Function(String);
