// Copyright (c) 2013, 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.

library source_file_provider;

import 'dart:async';
import 'dart:io';
import 'dart:typed_data';

import 'package:front_end/src/api_unstable/dart2js.dart' as fe;

import '../compiler_api.dart' as api;
import 'colors.dart' as colors;
import 'common/metrics.dart';
import 'io/source_file.dart';
import 'util/output_util.dart';

abstract class SourceFileByteReader {
  List<int> getBytes(String filename, {bool zeroTerminated = true});
}

abstract class SourceFileProvider implements api.CompilerInput {
  bool isWindows = (Platform.operatingSystem == 'windows');
  Uri cwd = Uri.base;
  int bytesRead = 0;
  int sourceBytesFromDill = 0;
  SourceFileByteReader byteReader;
  final Set<Uri> _registeredUris = {};
  final Map<Uri, Uri> _mappedUris = {};
  final bool disableByteCache;
  final Map<Uri, List<int>> _byteCache = {};

  SourceFileProvider(this.byteReader, {this.disableByteCache = true});

  Future<api.Input<List<int>>> readBytesFromUri(
      Uri resourceUri, api.InputKind inputKind) {
    if (!resourceUri.isAbsolute) {
      resourceUri = cwd.resolveUri(resourceUri);
    }
    if (resourceUri.isScheme('file')) {
      return _readFromFile(resourceUri, inputKind);
    } else {
      throw ArgumentError("Unknown scheme in uri '$resourceUri'");
    }
  }

  /// Adds [source] to the cache under the [resourceUri] key.
  api.Input<List<int>> _sourceToFile(
      Uri resourceUri, List<int> source, api.InputKind inputKind) {
    switch (inputKind) {
      case api.InputKind.UTF8:
        return Utf8BytesSourceFile(resourceUri, source);
      case api.InputKind.binary:
        return Binary(resourceUri, source);
    }
  }

  @override
  void registerUtf8ContentsForDiagnostics(Uri resourceUri, List<int> source) {
    if (!resourceUri.isAbsolute) {
      resourceUri = cwd.resolveUri(resourceUri);
    }

    registerUri(resourceUri);

    // Source bytes can be empty when the dill has source content erased. In
    // that case we should read the file contents from disk if we need them.
    if (!disableByteCache && source.isNotEmpty) {
      _byteCache[resourceUri] = source;
    }
    sourceBytesFromDill += source.length;
  }

  /// Registers the URI and returns true if the URI is new.
  bool registerUri(Uri uri) {
    return _registeredUris.add(uri);
  }

  api.Input<List<int>> _readFromFileSync(Uri uri, api.InputKind inputKind) {
    final resourceUri = _mappedUris[uri] ?? uri;
    assert(resourceUri.isScheme('file'));
    List<int> source;
    try {
      source = byteReader.getBytes(resourceUri.toFilePath(),
          zeroTerminated: inputKind == api.InputKind.UTF8);
    } on FileSystemException catch (ex) {
      String? message = ex.osError?.message;
      String detail = message != null ? ' ($message)' : '';
      throw "Error reading '${relativizeUri(resourceUri)}' $detail";
    }
    if (registerUri(resourceUri)) {
      bytesRead += source.length;
    }
    if (resourceUri != uri) {
      registerUri(uri);
    }
    return _sourceToFile(Uri.parse(relativizeUri(uri)), source, inputKind);
  }

  api.Input<List<int>>? _readFromFileSyncOrNull(
      Uri uri, api.InputKind inputKind) {
    try {
      return _readFromFileSync(uri, inputKind);
    } catch (_) {
      return null;
    }
  }

  /// Read [resourceUri] directly as a UTF-8 file. If reading fails, `null` is
  /// returned.
  api.Input<List<int>>? readUtf8FromFileSyncForTesting(Uri resourceUri) {
    try {
      return _readFromFileSync(resourceUri, api.InputKind.UTF8);
    } catch (e) {
      // Silence the error. The [resourceUri] was not requested by the user and
      // was only needed to give better error messages.
      return null;
    }
  }

  Future<api.Input<List<int>>> _readFromFile(
      Uri resourceUri, api.InputKind inputKind) {
    api.Input<List<int>> input;
    try {
      input = _readFromFileSync(resourceUri, inputKind);
    } catch (e) {
      return Future.error(e);
    }
    return Future.value(input);
  }

  /// Get the bytes for a previously accessed UTF-8 [Uri].
  api.Input<List<int>>? getUtf8SourceFile(Uri resourceUri) {
    if (!resourceUri.isAbsolute) {
      resourceUri = cwd.resolveUri(resourceUri);
    }

    if (_byteCache.containsKey(resourceUri)) {
      return _sourceToFile(
          resourceUri, _byteCache[resourceUri]!, api.InputKind.UTF8);
    }
    return resourceUri.isScheme('file')
        ? _readFromFileSyncOrNull(resourceUri, api.InputKind.UTF8)
        : null;
  }

  String relativizeUri(Uri uri) => fe.relativizeUri(cwd, uri, isWindows);

  // Note: this includes also indirect sources that were used to create
  // `.dill` inputs to the compiler. This is OK, since this API is only
  // used to calculate DEPS for gn build systems.
  Iterable<Uri> getSourceUris() => [..._registeredUris, ..._mappedUris.keys];
}

class MemoryCopySourceFileByteReader implements SourceFileByteReader {
  const MemoryCopySourceFileByteReader();
  @override
  List<int> getBytes(String filename, {bool zeroTerminated = true}) {
    return readAll(filename, zeroTerminated: zeroTerminated);
  }
}

Uint8List readAll(String filename, {bool zeroTerminated = true}) {
  RandomAccessFile file = File(filename).openSync();
  int length = file.lengthSync();
  int bufferLength = length;
  if (zeroTerminated) {
    // +1 to have a 0 terminated list, see [Scanner].
    bufferLength++;
  }
  var buffer = Uint8List(bufferLength);
  file.readIntoSync(buffer, 0, length);
  file.closeSync();
  return buffer;
}

class CompilerSourceFileProvider extends SourceFileProvider {
  CompilerSourceFileProvider(
      {SourceFileByteReader byteReader = const MemoryCopySourceFileByteReader(),
      super.disableByteCache})
      : super(byteReader);

  @override
  Future<api.Input<List<int>>> readFromUri(Uri uri,
          {api.InputKind inputKind = api.InputKind.UTF8}) =>
      readBytesFromUri(uri, inputKind);
}

class FormattingDiagnosticHandler implements api.CompilerDiagnostics {
  late final SourceFileProvider provider;
  bool showWarnings = true;
  bool showHints = true;
  bool verbose = false;
  bool isAborting = false;
  bool enableColors = false;
  bool throwOnError = false;
  int throwOnErrorCount = 0;
  api.Diagnostic? lastKind = null;
  int fatalCount = 0;

  final int FATAL = api.Diagnostic.crash.ordinal | api.Diagnostic.error.ordinal;
  final int INFO =
      api.Diagnostic.info.ordinal | api.Diagnostic.verboseInfo.ordinal;

  FormattingDiagnosticHandler();

  void registerFileProvider(SourceFileProvider provider) {
    this.provider = provider;
  }

  void info(String message,
      [api.Diagnostic kind = api.Diagnostic.verboseInfo]) {
    if (!verbose && kind == api.Diagnostic.verboseInfo) return;
    if (enableColors) {
      print('${colors.green("Info:")} $message');
    } else {
      print('Info: $message');
    }
  }

  /// Adds [kind] specific prefix to [message].
  String prefixMessage(String message, api.Diagnostic kind) {
    switch (kind) {
      case api.Diagnostic.error:
        return 'Error: $message';
      case api.Diagnostic.warning:
        return 'Warning: $message';
      case api.Diagnostic.hint:
        return 'Hint: $message';
      case api.Diagnostic.crash:
        return 'Internal Error: $message';
      case api.Diagnostic.context:
      case api.Diagnostic.info:
      case api.Diagnostic.verboseInfo:
        return 'Info: $message';
    }
  }

  @override
  void report(var code, Uri? uri, int? begin, int? end, String message,
      api.Diagnostic kind) {
    if (isAborting) return;
    isAborting = (kind == api.Diagnostic.crash);

    bool fatal = (kind.ordinal & FATAL) != 0;
    bool isInfo = (kind.ordinal & INFO) != 0;
    if (isInfo && uri == null && kind != api.Diagnostic.info) {
      info(message, kind);
      return;
    }

    message = prefixMessage(message, kind);

    // [lastKind] records the previous non-INFO kind we saw.
    // This is used to suppress info about a warning when warnings are
    // suppressed, and similar for hints.
    if (kind != api.Diagnostic.info) {
      lastKind = kind;
    }
    String Function(String) color;
    if (kind == api.Diagnostic.error) {
      color = colors.red;
    } else if (kind == api.Diagnostic.warning) {
      if (!showWarnings) return;
      color = colors.magenta;
    } else if (kind == api.Diagnostic.hint) {
      if (!showHints) return;
      color = colors.cyan;
    } else if (kind == api.Diagnostic.crash) {
      color = colors.red;
    } else if (kind == api.Diagnostic.info) {
      color = colors.green;
    } else if (kind == api.Diagnostic.context) {
      if (lastKind == api.Diagnostic.warning && !showWarnings) return;
      if (lastKind == api.Diagnostic.hint && !showHints) return;
      color = colors.green;
    } else {
      throw 'Unknown kind: $kind (${kind.ordinal})';
    }
    if (!enableColors) {
      color = (String x) => x;
    }
    if (uri == null) {
      print('${color(message)}');
    } else {
      api.Input<List<int>>? file = provider.getUtf8SourceFile(uri);
      if (file is SourceFile && begin != null && end != null) {
        print(file.getLocationMessage(color(message), begin, end,
            colorize: color));
      } else {
        String position = begin != null && end != null && end - begin > 0
            ? '@$begin+${end - begin}'
            : '';
        print('${provider.relativizeUri(uri)}$position:\n'
            '${color(message)}');
      }
    }
    if (fatal && ++fatalCount >= throwOnErrorCount && throwOnError) {
      isAborting = true;
      throw _CompilationErrorError(message);
    }
  }
}

class _CompilationErrorError {
  final String message;
  _CompilationErrorError(this.message);
  @override
  String toString() => 'Aborted due to --throw-on-error: $message';
}

typedef OnInfo = void Function(String message);
typedef OnFailure = Never Function(String message);

class RandomAccessFileOutputProvider implements api.CompilerOutput {
  // The file name to use for the main output. Also used as the filename prefix
  // for other URIs generated from this output provider. If `null` there is no
  // primary output but can still write other files.
  final Uri? out;
  final Uri? sourceMapOut;
  final OnInfo onInfo;
  final OnFailure onFailure;

  int totalCharactersWritten = 0;
  int totalCharactersWrittenPrimary = 0;
  int totalCharactersWrittenJavaScript = 0;
  int totalDataWritten = 0;

  List<String> allOutputFiles = <String>[];

  RandomAccessFileOutputProvider(this.out, this.sourceMapOut,
      {required this.onInfo, required this.onFailure});

  Uri createUri(String name, String extension, api.OutputType type) {
    Uri uri;
    // TODO(johnniwinther): Unify handle of [name] and [extension] to prepare
    // for using a single, possibly relative, [uri] as input.
    switch (type) {
      case api.OutputType.js:
        if (name == '') {
          uri = out!;
        } else {
          uri = out!.resolve('$name.$extension');
        }
        break;
      case api.OutputType.sourceMap:
        if (name == '') {
          uri = sourceMapOut!;
        } else {
          uri = out!.resolve('$name.$extension');
        }
        break;
      case api.OutputType.jsPart:
        uri = out!.resolve('$name.$extension');
        break;
      case api.OutputType.deferredLoadIds:
        assert(name.isNotEmpty);
        return (out ?? Uri.base).resolve(name);
      case api.OutputType.dumpInfo:
      case api.OutputType.dumpUnusedLibraries:
      case api.OutputType.deferredMap:
      case api.OutputType.resourceIdentifiers:
        if (name == '') {
          name = out!.pathSegments.last;
        }
        if (extension == '') {
          uri = out!.resolve(name);
        } else {
          uri = out!.resolve('$name.$extension');
        }
        break;
      case api.OutputType.debug:
        if (name == '') {
          name = out!.pathSegments.last;
        }
        uri = out!.resolve('$name.$extension');
        break;
    }
    return uri;
  }

  @override
  api.OutputSink createOutputSink(
      String name, String extension, api.OutputType type) {
    Uri uri = createUri(name, extension, type);
    bool isPrimaryOutput = uri == out;

    if (!uri.isScheme('file')) {
      onFailure('Unhandled scheme ${uri.scheme} in $uri.');
    }

    RandomAccessFile output;
    try {
      output = (File(uri.toFilePath())..createSync(recursive: true))
          .openSync(mode: FileMode.write);
    } on FileSystemException catch (e) {
      onFailure('$e');
    }

    allOutputFiles.add(fe.relativizeUri(Uri.base, uri, Platform.isWindows));

    void onClose(int charactersWritten) {
      totalCharactersWritten += charactersWritten;
      if (isPrimaryOutput) {
        totalCharactersWrittenPrimary += charactersWritten;
      }
      if (type == api.OutputType.js || type == api.OutputType.jsPart) {
        totalCharactersWrittenJavaScript += charactersWritten;
      }
    }

    return BufferedStringSinkWrapper(
        FileStringOutputSink(output, onClose: onClose));
  }

  @override
  api.BinaryOutputSink createBinarySink(Uri uri) {
    uri = Uri.base.resolveUri(uri);

    allOutputFiles.add(fe.relativizeUri(Uri.base, uri, Platform.isWindows));

    if (!uri.isScheme('file')) {
      onFailure('Unhandled scheme ${uri.scheme} in $uri.');
    }

    RandomAccessFile output;
    try {
      output = (File(uri.toFilePath())..createSync(recursive: true))
          .openSync(mode: FileMode.write);
    } on FileSystemException catch (e) {
      onFailure('$e');
    }

    void onClose(int bytesWritten) {
      totalDataWritten += bytesWritten;
    }

    return FileBinaryOutputSink(output, onClose: onClose);
  }
}

class RandomAccessBinaryOutputSink implements api.BinaryOutputSink {
  final RandomAccessFile output;

  RandomAccessBinaryOutputSink(Uri uri)
      : output = File.fromUri(uri).openSync(mode: FileMode.write);

  @override
  void add(List<int> buffer, [int start = 0, int? end]) {
    output.writeFromSync(buffer, start, end);
  }

  @override
  void close() {
    output.closeSync();
  }
}

/// Adapter to integrate dart2js in bazel.
///
/// To handle bazel's special layout:
///
///  * We specify a .dart_tool/package_config.json configuration file that
///    expands packages to their corresponding bazel location.
///    This way there is no need to create a pub
///    cache prior to invoking dart2js.
///
///  * We provide an implicit mapping that can make all urls relative to the
///  bazel root.
///    To the compiler, URIs look like:
///      file:///bazel-root/a/b/c.dart
///
///    even though in the file system the file is located at:
///      file:///path/to/the/actual/bazel/root/a/b/c.dart
///
///    This mapping serves two purposes:
///      - It makes compiler results independent of the machine layout, which
///        enables us to share results across bazel runs and across machines.
///
///      - It hides the distinction between generated and source files. That way
///      we can use the standard package-resolution mechanism and ignore the
///      internals of how files are organized within bazel.
///
/// When invoking the compiler, bazel will use `package:` and
/// `file:///bazel-root/` URIs to specify entrypoints.
///
/// The mapping is specified using search paths relative to the current
/// directory. When this provider looks up a file, the bazel-root folder is
/// replaced by the first directory in the search path containing the file, if
/// any. For example, given the search path ".,bazel-bin/", and a URL
/// of the form `file:///bazel-root/a/b.dart`, this provider will check if the
/// file exists under "./a/b.dart", then check under "bazel-bin/a/b.dart".  If
/// none of the paths matches, it will attempt to load the file from
/// `/bazel-root/a/b.dart` which will likely fail.
class BazelInputProvider extends SourceFileProvider {
  final List<Uri> dirs;

  BazelInputProvider(List<String> searchPaths, super.byteReader,
      {super.disableByteCache})
      : dirs = searchPaths.map(_resolve).toList();

  static Uri _resolve(String path) => Uri.base.resolve(path);

  @override
  Future<api.Input<List<int>>> readFromUri(Uri uri,
      {api.InputKind inputKind = api.InputKind.UTF8}) async {
    var resolvedUri = uri;
    var path = uri.path;
    if (path.startsWith('/bazel-root')) {
      path = path.substring('/bazel-root/'.length);
      for (var dir in dirs) {
        var file = dir.resolve(path);
        if (await File.fromUri(file).exists()) {
          resolvedUri = file;
          break;
        }
      }
    }
    api.Input<List<int>> result =
        await readBytesFromUri(resolvedUri, inputKind);
    if (uri != resolvedUri) {
      if (!resolvedUri.isAbsolute) {
        resolvedUri = cwd.resolveUri(resolvedUri);
      }
      _mappedUris[uri] = resolvedUri;
    }
    return result;
  }
}

/// Adapter to support one or more synthetic uri schemes.
///
/// These custom uris map to one or more real directories on the file system,
/// providing a merged view - or "overlay" file system.
///
/// This also allows for hermetic builds which do not encode machine specific
/// absolute uris by creating a synthetic "root" of the file system.
///
/// TODO(sigmund): Remove the [BazelInputProvider] in favor of this.
/// TODO(sigmund): Remove this and use the common `MultiRootFileSystem`
/// implementation.
class MultiRootInputProvider extends SourceFileProvider {
  final List<Uri> roots;
  final String markerScheme;

  MultiRootInputProvider(this.markerScheme, this.roots, super.byteReader,
      {super.disableByteCache});

  @override
  Future<api.Input<List<int>>> readFromUri(Uri uri,
      {api.InputKind inputKind = api.InputKind.UTF8}) async {
    var resolvedUri = uri;
    if (resolvedUri.isScheme(markerScheme)) {
      var path = resolvedUri.path;
      if (path.startsWith('/')) path = path.substring(1);
      for (var dir in roots) {
        var fileUri = dir.resolve(path);
        if (await File.fromUri(fileUri).exists()) {
          resolvedUri = fileUri;
          break;
        }
      }
    }
    api.Input<List<int>> result =
        await readBytesFromUri(resolvedUri, inputKind);
    _mappedUris[uri] = resolvedUri;
    return result;
  }
}

class DataReadMetrics extends MetricsBase {
  @override
  String get namespace => 'input';
  CountMetric inputBytes = CountMetric('inputBytes');
  CountMetric sourceBytes = CountMetric('sourceBytes');

  void addDataRead(api.CompilerInput input) {
    if (input is SourceFileProvider) {
      inputBytes.add(input.bytesRead);
      sourceBytes.add(input.sourceBytesFromDill);
      if (primary.isEmpty) {
        primary = [inputBytes, sourceBytes];
      }
    }
  }
}
