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

library fasta.compiler_context;

import 'dart:async' show Zone, runZoned;

import 'package:_fe_analyzer_shared/src/messages/codes.dart';
import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:_fe_analyzer_shared/src/util/colors.dart' as colors;

import 'package:_fe_analyzer_shared/src/scanner/token_impl.dart'
    show StringToken;

import 'package:kernel/ast.dart' show Source;

import '../api_prototype/file_system.dart' show FileSystem;

import '../base/processed_options.dart' show ProcessedOptions;

import 'command_line_reporting.dart' as command_line_reporting;

final Object compilerContextKey = new Object();

/// Shared context used throughout the compiler.
///
/// The compiler works with a single instance of this class. To avoid
/// passing it around as an argument everywhere, it is stored as a zone-value.
///
/// For convenience the static getter [CompilerContext.current] retrieves the
/// context stored in the current zone.
class CompilerContext {
  // TODO(sigmund): Move here any method in ProcessedOptions that doesn't seem
  // appropriate as an "option", or consider merging ProcessedOptions entirely
  // within this class, and depend only on the raw options here.
  final ProcessedOptions options;

  /// Sources seen by the compiler.
  ///
  /// This is populated as the compiler reads files, and it is used for error
  /// reporting and to generate source location information in the compiled
  /// programs.
  final Map<Uri, Source> uriToSource = <Uri, Source>{};

  // TODO(ahe): Remove this.
  final List<Object> errors = <Object>[];

  final List<Uri> dependencies = <Uri>[];

  FileSystem get fileSystem => options.fileSystem;

  Uri? cachedSdkRoot = null;

  bool compilingPlatform = false;

  CompilerContext(this.options) {
    if (options.verbose) {
      colors.printEnableColorsReason = print;
    }
  }

  /// Report [message], for example, by printing it.
  void report(LocatedMessage message, Severity severity,
      {List<LocatedMessage>? context, List<Uri>? involvedFiles}) {
    options.report(message, severity,
        context: context, involvedFiles: involvedFiles);
  }

  /// Report [message], for example, by printing it.
  // TODO(askesc): Remove this and direct callers directly to report.
  void reportWithoutLocation(Message message, Severity severity) {
    options.reportWithoutLocation(message, severity);
  }

  /// Format [message] as a text string that can be included in generated code.
  PlainAndColorizedString format(LocatedMessage message, Severity severity) {
    return command_line_reporting.format(message, severity);
  }

  // TODO(ahe): Remove this.
  void logError(Object message, Severity severity) {
    errors.add(message);
    errors.add(severity);
  }

  static void recordDependency(Uri uri) {
    if (!uri.isScheme("file") && !uri.isScheme("http")) {
      throw new ArgumentError("Expected a file or http URI, but got: '$uri'.");
    }
    CompilerContext? context = Zone.current[compilerContextKey];
    if (context != null) {
      context.dependencies.add(uri);
    }
  }

  static CompilerContext get current {
    CompilerContext? context = Zone.current[compilerContextKey];
    if (context == null) {
      // Note: we throw directly and don't use internalProblem, because
      // internalProblem depends on having a compiler context available.
      String problemMessage =
          messageInternalProblemMissingContext.problemMessage;
      String correctionMessage =
          messageInternalProblemMissingContext.correctionMessage!;
      throw "Internal problem: $problemMessage\nTip: $correctionMessage";
    }
    return context;
  }

  static bool get isActive => Zone.current[compilerContextKey] != null;

  /// Perform [action] in a [Zone] where [this] will be available as
  /// `CompilerContext.current`.
  Future<T> runInContext<T>(Future<T> action(CompilerContext c)) {
    return runZoned(
        () => new Future<T>.sync(() => action(this)).whenComplete(clear),
        zoneValues: {compilerContextKey: this});
  }

  /// Perform [action] in a [Zone] where [options] will be available as
  /// `CompilerContext.current.options`.
  static Future<T> runWithOptions<T>(
      ProcessedOptions options, Future<T> action(CompilerContext c),
      {bool errorOnMissingInput: true}) {
    return new CompilerContext(options)
        .runInContext<T>((CompilerContext c) async {
      await options.validateOptions(errorOnMissingInput: errorOnMissingInput);
      return action(c);
    });
  }

  static Future<T> runWithDefaultOptions<T>(
      Future<T> action(CompilerContext c)) {
    return new CompilerContext(new ProcessedOptions()).runInContext<T>(action);
  }

  void clear() {
    StringToken.canonicalizer.clear();
    errors.clear();
    dependencies.clear();
  }
}
