#!/usr/bin/env dart
// 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:io';

import 'batch_util.dart';

import 'package:args/args.dart';
import 'package:kernel/analyzer/loader.dart';
import 'package:kernel/application_root.dart';
import 'package:kernel/verifier.dart';
import 'package:kernel/kernel.dart';
import 'package:kernel/log.dart';
import 'package:kernel/target/targets.dart';
import 'package:path/path.dart' as path;

// Returns the path to the current sdk based on `Platform.resolvedExecutable`.
String currentSdk() {
  // The dart executable should be inside dart-sdk/bin/dart.
  return path.dirname(path.dirname(path.absolute(Platform.resolvedExecutable)));
}

ArgParser parser = new ArgParser(allowTrailingOptions: true)
  ..addOption('format',
      abbr: 'f',
      allowed: ['text', 'bin'],
      help: 'Output format.\n'
          '(defaults to "text" unless output file ends with ".dill")')
  ..addOption('out',
      abbr: 'o',
      help: 'Output file.\n'
          '(defaults to "out.dill" if format is "bin", otherwise stdout)')
  ..addOption('sdk', defaultsTo: currentSdk(), help: 'Path to the Dart SDK.')
  ..addOption('packages',
      abbr: 'p', help: 'Path to the .packages file or packages folder.')
  ..addOption('package-root', help: 'Deprecated alias for --packages')
  ..addOption('app-root',
      help: 'Store library paths relative to the given directory.\n'
          'If none is given, absolute paths are used.\n'
          'Application libraries not inside the application root are stored '
          'using absolute paths')
  ..addOption('target',
      abbr: 't',
      help: 'Tailor the IR to the given target.',
      allowed: targetNames,
      defaultsTo: 'vm')
  ..addFlag('strong',
      help: 'Load .dart files in strong mode.\n'
          'Does not affect loading of binary files. Strong mode support is very\n'
          'unstable and not well integrated yet.')
  ..addFlag('link', abbr: 'l', help: 'Link the whole program into one file.')
  ..addFlag('no-output', negatable: false, help: 'Do not output any files.')
  ..addOption('url-mapping',
      allowMultiple: true,
      help: 'A custom url mapping of the form `<scheme>:<name>::<uri>`.')
  ..addFlag('verbose',
      abbr: 'v',
      negatable: false,
      help: 'Print internal warnings and diagnostics to stderr.')
  ..addFlag('print-metrics',
      negatable: false, help: 'Print performance metrics.')
  ..addOption('write-dependencies',
      help: 'Write all the .dart that were loaded to the given file.')
  ..addFlag('verify-ir', help: 'Perform slow internal correctness checks.')
  ..addFlag('tolerant',
      help: 'Generate kernel even if there are compile-time errors.',
      defaultsTo: false)
  ..addOption('D',
      abbr: 'D',
      allowMultiple: true,
      help: 'Define an environment variable.',
      hide: true)
  ..addFlag('show-external',
      help: 'When printing a library as text, also print its dependencies\n'
          'on external libraries.')
  ..addFlag('show-offsets',
      help: 'When printing a library as text, also print node offsets');

String getUsage() => """
Usage: dartk [options] FILE

Convert .dart or .dill files to kernel's IR and print out its textual
or binary form.

Examples:
    dartk foo.dart            # print text IR for foo.dart
    dartk foo.dart -ofoo.dill # write binary IR for foo.dart to foo.dill
    dartk foo.dill            # print text IR for binary file foo.dill

Options:
${parser.usage}

    -D<name>=<value>        Define an environment variable.
""";

dynamic fail(String message) {
  stderr.writeln(message);
  exit(1);
  return null;
}

ArgResults options;

String defaultFormat() {
  if (options['out'] != null && options['out'].endsWith('.dill')) {
    return 'bin';
  }
  return 'text';
}

String defaultOutput() {
  if (options['format'] == 'bin') {
    return 'out.dill';
  }
  return null;
}

void checkIsDirectoryOrNull(String path, String option) {
  if (path == null) return;
  var stat = new File(path).statSync();
  switch (stat.type) {
    case FileSystemEntityType.DIRECTORY:
    case FileSystemEntityType.LINK:
      return;
    case FileSystemEntityType.NOT_FOUND:
      throw fail('$option not found: $path');
    default:
      fail('$option is not a directory: $path');
  }
}

void checkIsFile(String path, {String option}) {
  var stat = new File(path).statSync();
  switch (stat.type) {
    case FileSystemEntityType.DIRECTORY:
      throw fail('$option is a directory: $path');

    case FileSystemEntityType.NOT_FOUND:
      throw fail('$option not found: $path');
  }
}

void checkIsFileOrDirectoryOrNull(String path, String option) {
  if (path == null) return;
  var stat = new File(path).statSync();
  if (stat.type == FileSystemEntityType.NOT_FOUND) {
    fail('$option not found: $path');
  }
}

int getTotalSourceSize(List<String> files) {
  int size = 0;
  for (var filename in files) {
    size += new File(filename).statSync().size;
  }
  return size;
}

bool get shouldReportMetrics => options['print-metrics'];

void dumpString(String value, [String filename]) {
  if (filename == null) {
    print(value);
  } else {
    new File(filename).writeAsStringSync(value);
  }
}

Map<Uri, Uri> parseCustomUriMappings(List<String> mappings) {
  Map<Uri, Uri> customUriMappings = <Uri, Uri>{};

  fatal(String mapping) {
    fail('Invalid uri mapping "$mapping". Each mapping should have the '
        'form "<scheme>:<name>::<uri>".');
  }

  // Each mapping has the form <uri>::<uri>.
  for (var mapping in mappings) {
    List<String> parts = mapping.split('::');
    if (parts.length != 2) {
      fatal(mapping);
    }
    Uri fromUri = Uri.parse(parts[0]);
    if (fromUri.scheme == '' || fromUri.path.contains('/')) {
      fatal(mapping);
    }
    Uri toUri = Uri.parse(parts[1]);
    if (toUri.scheme == '') {
      toUri = new Uri.file(path.absolute(parts[1]));
    }
    customUriMappings[fromUri] = toUri;
  }

  return customUriMappings;
}

/// Maintains state that should be shared between batched executions when
/// running in batch mode (for testing purposes).
///
/// This reuses the analyzer's in-memory copy of the Dart SDK between runs.
class BatchModeState {
  bool isBatchMode = false;
  DartLoaderBatch batch = new DartLoaderBatch();
}

main(List<String> args) async {
  if (args.isNotEmpty && args[0] == '--batch') {
    if (args.length != 1) {
      return fail('--batch cannot be used with other arguments');
    }
    var batchModeState = new BatchModeState()..isBatchMode = true;
    await runBatch((args) => batchMain(args, batchModeState));
  } else {
    CompilerOutcome outcome = await batchMain(args, new BatchModeState());
    exit(outcome == CompilerOutcome.Ok ? 0 : 1);
  }
}

bool isSupportedArgument(String arg) {
  if (arg.startsWith('--')) {
    int equals = arg.indexOf('=');
    var name = equals != -1 ? arg.substring(2, equals) : arg.substring(2);
    return parser.options.containsKey(name);
  }
  if (arg.startsWith('-')) {
    return parser.findByAbbreviation(arg.substring(1)) != null;
  }
  return true;
}

Future<CompilerOutcome> batchMain(
    List<String> args, BatchModeState batchModeState) async {
  if (args.contains('--ignore-unrecognized-flags')) {
    args = args.where(isSupportedArgument).toList();
  }

  if (args.isEmpty) {
    return fail(getUsage());
  }

  try {
    options = parser.parse(args);
  } on FormatException catch (e) {
    return fail(e.message); // Don't puke stack traces.
  }

  checkIsDirectoryOrNull(options['sdk'], 'Dart SDK');

  String packagePath = options['packages'] ?? options['package-root'];
  checkIsFileOrDirectoryOrNull(packagePath, 'Package root or .packages');

  String applicationRootOption = options['app-root'];
  checkIsDirectoryOrNull(applicationRootOption, 'Application root');
  if (applicationRootOption != null) {
    applicationRootOption = new File(applicationRootOption).absolute.path;
  }
  var applicationRoot = new ApplicationRoot(applicationRootOption);

  // Set up logging.
  if (options['verbose']) {
    log.onRecord.listen((LogRecord rec) {
      stderr.writeln(rec.message);
    });
  }

  if (options.rest.length != 1) {
    return fail('Exactly one FILE should be given.');
  }

  String file = options.rest.single;
  checkIsFile(file, option: 'Input file');
  file = new File(file).absolute.path;
  Uri fileUri = new Uri(scheme: 'file', path: file);

  String format = options['format'] ?? defaultFormat();
  String outputFile = options['out'] ?? defaultOutput();

  List<String> urlMapping = options['url-mapping'] as List<String>;
  var customUriMappings = parseCustomUriMappings(urlMapping);
  var repository = new Repository();

  Program program;

  var watch = new Stopwatch()..start();
  List<String> loadedFiles;
  Function getLoadedFiles;
  List errors = const [];
  TargetFlags targetFlags = new TargetFlags(strongMode: options['strong']);
  Target target = getTarget(options['target'], targetFlags);

  var declaredVariables = <String, String>{};
  declaredVariables.addAll(target.extraDeclaredVariables);
  for (String define in options['D']) {
    int separator = define.indexOf('=');
    if (separator == -1) {
      fail('Invalid define: -D$define. Format is -D<name>=<value>');
    }
    String name = define.substring(0, separator);
    String value = define.substring(separator + 1);
    declaredVariables[name] = value;
  }

  if (file.endsWith('.dill')) {
    program = loadProgramFromBinary(file, repository);
    getLoadedFiles = () => [file];
  } else {
    DartOptions dartOptions = new DartOptions(
        strongMode: target.strongMode,
        strongModeSdk: target.strongModeSdk,
        sdk: options['sdk'],
        packagePath: packagePath,
        customUriMappings: customUriMappings,
        declaredVariables: declaredVariables,
        applicationRoot: applicationRoot);
    String packageDiscoveryPath = batchModeState.isBatchMode ? null : file;
    DartLoader loader = await batchModeState.batch.getLoader(
        repository, dartOptions,
        packageDiscoveryPath: packageDiscoveryPath);
    if (options['link']) {
      program = loader.loadProgram(fileUri, target: target);
    } else {
      var library = loader.loadLibrary(fileUri);
      assert(library ==
          repository.getLibraryReference(applicationRoot.relativeUri(fileUri)));
      program = new Program(repository.libraries);
    }
    errors = loader.errors;
    if (errors.isNotEmpty) {
      const int errorLimit = 100;
      stderr.writeln(errors.take(errorLimit).join('\n'));
      if (errors.length > errorLimit) {
        stderr
            .writeln('[error] ${errors.length - errorLimit} errors not shown');
      }
    }
    getLoadedFiles = () => loadedFiles ??= loader.getLoadedFileNames();
  }

  bool canContinueCompilation = errors.isEmpty || options['tolerant'];

  int loadTime = watch.elapsedMilliseconds;
  if (shouldReportMetrics) {
    print('loader.time = $loadTime ms');
  }

  void runVerifier() {
    if (options['verify-ir']) {
      verifyProgram(program);
    }
  }

  if (canContinueCompilation) {
    runVerifier();
  }

  String outputDependencies = options['write-dependencies'];
  if (outputDependencies != null) {
    new File(outputDependencies).writeAsStringSync(getLoadedFiles().join('\n'));
  }

  // Apply target-specific transformations.
  if (target != null && options['link'] && canContinueCompilation) {
    target.transformProgram(program);
    runVerifier();
  }

  if (options['no-output']) {
    return CompilerOutcome.Ok;
  }

  watch.reset();

  Future ioFuture;
  if (canContinueCompilation) {
    switch (format) {
      case 'text':
        writeProgramToText(program,
            path: outputFile,
            showExternal: options['show-external'],
            showOffsets: options['show-offsets']);
        break;
      case 'bin':
        ioFuture = writeProgramToBinary(program, outputFile);
        break;
    }
  }

  int time = watch.elapsedMilliseconds;
  if (shouldReportMetrics) {
    print('writer.time = $time ms');
  }

  await ioFuture;

  if (shouldReportMetrics) {
    int flushTime = watch.elapsedMilliseconds - time;
    print('writer.flush_time = $flushTime ms');
  }

  return errors.length > 0 ? CompilerOutcome.Fail : CompilerOutcome.Ok;
}
