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

/// Defines [ForwardConstantEvaluationErrors], an implementation of
/// [constants.ErrorReporter] which uses package:front_end to report errors.
library vm.constants_error_reporter;

import 'package:front_end/src/api_unstable/vm.dart'
    show CompilerContext, Severity;

import 'package:front_end/src/api_unstable/vm.dart' as codes;

import 'package:kernel/ast.dart'
    show Constant, DartType, FileUriNode, IntConstant, Procedure, TreeNode;
import 'package:kernel/transformations/constants.dart' as constants;
import 'package:kernel/type_environment.dart' show TypeEnvironment;

class ForwardConstantEvaluationErrors implements constants.ErrorReporter {
  // This will get the currently active [CompilerContext] from a zone variable.
  // If there is no active context, this will throw.
  final CompilerContext compilerContext = CompilerContext.current;

  final TypeEnvironment typeEnvironment;

  ForwardConstantEvaluationErrors(this.typeEnvironment);

  freeTypeParameter(List<TreeNode> context, TreeNode node, DartType type) {
    final message =
        codes.templateConstEvalFreeTypeParameter.withArguments(type);
    reportIt(context, message, node);
  }

  duplicateKey(List<TreeNode> context, TreeNode node, Constant key) {
    final message = codes.templateConstEvalDuplicateKey.withArguments(key);
    reportIt(context, message, node);
  }

  invalidDartType(List<TreeNode> context, TreeNode node, Constant receiver,
      DartType expectedType) {
    final message = codes.templateConstEvalInvalidType.withArguments(
        receiver, expectedType, receiver.getType(typeEnvironment));
    reportIt(context, message, node);
  }

  invalidBinaryOperandType(
      List<TreeNode> context,
      TreeNode node,
      Constant receiver,
      String op,
      DartType expectedType,
      DartType actualType) {
    final message = codes.templateConstEvalInvalidBinaryOperandType
        .withArguments(op, receiver, expectedType, actualType);
    reportIt(context, message, node);
  }

  invalidMethodInvocation(
      List<TreeNode> context, TreeNode node, Constant receiver, String op) {
    final message = codes.templateConstEvalInvalidMethodInvocation
        .withArguments(op, receiver);
    reportIt(context, message, node);
  }

  invalidStaticInvocation(
      List<TreeNode> context, TreeNode node, Procedure target) {
    final message = codes.templateConstEvalInvalidStaticInvocation
        .withArguments(target.name.toString());
    reportIt(context, message, node);
  }

  invalidStringInterpolationOperand(
      List<TreeNode> context, TreeNode node, Constant constant) {
    final message = codes.templateConstEvalInvalidStringInterpolationOperand
        .withArguments(constant);
    reportIt(context, message, node);
  }

  invalidSymbolName(List<TreeNode> context, TreeNode node, Constant constant) {
    final message =
        codes.templateConstEvalInvalidSymbolName.withArguments(constant);
    reportIt(context, message, node);
  }

  zeroDivisor(
      List<TreeNode> context, TreeNode node, IntConstant receiver, String op) {
    final message = codes.templateConstEvalZeroDivisor
        .withArguments(op, '${receiver.value}');
    reportIt(context, message, node);
  }

  negativeShift(List<TreeNode> context, TreeNode node, IntConstant receiver,
      String op, IntConstant argument) {
    final message = codes.templateConstEvalNegativeShift
        .withArguments(op, '${receiver.value}', '${argument.value}');
    reportIt(context, message, node);
  }

  nonConstLiteral(List<TreeNode> context, TreeNode node, String klass) {
    final message =
        codes.templateConstEvalNonConstantLiteral.withArguments(klass);
    reportIt(context, message, node);
  }

  failedAssertion(List<TreeNode> context, TreeNode node, String string) {
    final message = string == null
        ? codes.messageConstEvalFailedAssertion
        : codes.templateConstEvalFailedAssertionWithMessage
            .withArguments(string);
    reportIt(context, message, node);
  }

  nonConstantVariableGet(
      List<TreeNode> context, TreeNode node, String variableName) {
    final message = codes.templateConstEvalNonConstantVariableGet
        .withArguments(variableName);
    reportIt(context, message, node);
  }

  deferredLibrary(List<TreeNode> context, TreeNode node, String importName) {
    final message =
        codes.templateConstEvalDeferredLibrary.withArguments(importName);
    reportIt(context, message, node);
  }

  reportIt(List<TreeNode> context, codes.Message message, TreeNode node) {
    final Uri uri = getFileUri(node);
    final int fileOffset = getFileOffset(node);

    final contextMessages = <codes.LocatedMessage>[];
    for (final TreeNode node in context) {
      final Uri uri = getFileUri(node);
      final int fileOffset = getFileOffset(node);
      contextMessages.add(codes.messageConstEvalContext
          .withLocation(uri, fileOffset, codes.noLength));
    }

    final locatedMessage =
        message.withLocation(uri, fileOffset, codes.noLength);

    compilerContext.options
        .report(locatedMessage, Severity.error, context: contextMessages);
  }

  getFileUri(TreeNode node) {
    while (node is! FileUriNode) {
      node = node.parent;
    }
    return (node as FileUriNode).fileUri;
  }

  getFileOffset(TreeNode node) {
    while (node?.fileOffset == TreeNode.noOffset) {
      node = node.parent;
    }
    return node == null ? TreeNode.noOffset : node.fileOffset;
  }
}
