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

/// This is for use in extracting messages from a Dart program
/// using the Intl.message() mechanism and writing them to a file for
/// translation. This provides only the stub of a mechanism, because it
/// doesn't define how the file should be written. It provides an
/// [IntlMessage] class that holds the extracted data and [parseString]
/// and [parseFile] methods which
/// can extract messages that conform to the expected pattern:
///       (parameters) => Intl.message("Message $parameters", desc: ...);
/// It uses the analyzer package to do the parsing, so may
/// break if there are changes to the API that it provides.
/// An example can be found in test/message_extraction/extract_to_json.dart
///
/// Note that this does not understand how to follow part directives, so it
/// has to explicitly be given all the files that it needs. A typical use case
/// is to run it on all .dart files in a directory.
library extract_messages;

import 'dart:io';

import 'package:analyzer/analyzer.dart';
import 'package:intl/src/intl_message.dart';

/// A function that takes a message and does something useful with it.
typedef void OnMessage(String message);

/// A particular message extraction run.
///
///  This encapsulates all the state required for message extraction so that
///  it can be run inside a persistent process.
class MessageExtraction {
  /// What to do when a message is encountered, defaults to [print].
  OnMessage onMessage = print;

  /// If this is true, print warnings for skipped messages. Otherwise, warnings
  /// are suppressed.
  bool suppressWarnings = false;

  /// If this is true, then treat all warnings as errors.
  bool warningsAreErrors = false;

  /// This accumulates a list of all warnings/errors we have found. These are
  /// saved as strings right now, so all that can really be done is print and
  /// count them.
  List<String> warnings = [];

  /// Were there any warnings or errors in extracting messages.
  bool get hasWarnings => warnings.isNotEmpty;

  /// Are plural and gender expressions required to be at the top level
  /// of an expression, or are they allowed to be embedded in string literals.
  ///
  /// For example, the following expression
  ///     'There are ${Intl.plural(...)} items'.
  /// is legal if [allowEmbeddedPluralsAndGenders] is true, but illegal
  /// if [allowEmbeddedPluralsAndGenders] is false.
  bool allowEmbeddedPluralsAndGenders = true;

  /// Parse the source of the Dart program file [file] and return a Map from
  /// message names to [IntlMessage] instances.
  ///
  /// If [transformer] is true, assume the transformer will supply any "name"
  /// and "args" parameters required in Intl.message calls.
  Map<String, MainMessage> parseFile(File file, [transformer = false]) {
    // Optimization to avoid parsing files we're sure don't contain any messages.
    String contents = file.readAsStringSync();
    origin = file.path;
    if (contents.contains("Intl.")) {
      root = _parseCompilationUnit(contents, origin);
    } else {
      return {};
    }
    var visitor = new MessageFindingVisitor(this);
    visitor.generateNameAndArgs = transformer;
    root.accept(visitor);
    return visitor.messages;
  }

  CompilationUnit _parseCompilationUnit(String contents, String origin) {
    var parsed;
    try {
      parsed = parseCompilationUnit(contents);
    } on AnalyzerErrorGroup catch (e) {
      print("Error in parsing $origin, no messages extracted.");
      print("  $e");
    }
    return parsed;
  }

  /// The root of the compilation unit, and the first node we visit. We hold
  /// on to this for error reporting, as it can give us line numbers of other
  /// nodes.
  CompilationUnit root;

  /// An arbitrary string describing where the source code came from. Most
  /// obviously, this could be a file path. We use this when reporting
  /// invalid messages.
  String origin;

  String _reportErrorLocation(AstNode node) {
    var result = new StringBuffer();
    if (origin != null) result.write("    from $origin");
    var info = root.lineInfo;
    if (info != null) {
      var line = info.getLocation(node.offset);
      result
          .write("    line: ${line.lineNumber}, column: ${line.columnNumber}");
    }
    return result.toString();
  }
}

/// This visits the program source nodes looking for Intl.message uses
/// that conform to its pattern and then creating the corresponding
/// IntlMessage objects. We have to find both the enclosing function, and
/// the Intl.message invocation.
class MessageFindingVisitor extends GeneralizingAstVisitor {
  MessageFindingVisitor(this.extraction);

  /// The message extraction in which we are running.
  final MessageExtraction extraction;

  /// Accumulates the messages we have found, keyed by name.
  final Map<String, MainMessage> messages = new Map<String, MainMessage>();

  /// Should we generate the name and arguments from the function definition,
  /// meaning we're running in the transformer.
  bool generateNameAndArgs = false;

  /// We keep track of the data from the last MethodDeclaration,
  /// FunctionDeclaration or FunctionExpression that we saw on the way down,
  /// as that will be the nearest parent of the Intl.message invocation.
  FormalParameterList parameters;
  String name;

  /// Return true if [node] matches the pattern we expect for Intl.message()
  bool looksLikeIntlMessage(MethodInvocation node) {
    const validNames = const ["message", "plural", "gender", "select"];
    if (!validNames.contains(node.methodName.name)) return false;
    if (!(node.target is SimpleIdentifier)) return false;
    SimpleIdentifier target = node.target;
    return target.token.toString() == "Intl";
  }

  Message _expectedInstance(String type) {
    switch (type) {
      case 'message':
        return new MainMessage();
      case 'plural':
        return new Plural();
      case 'gender':
        return new Gender();
      case 'select':
        return new Select();
      default:
        return null;
    }
  }

  /// Returns a String describing why the node is invalid, or null if no
  /// reason is found, so it's presumed valid.
  String checkValidity(MethodInvocation node) {
    // The containing function cannot have named parameters.
    if (parameters.parameters.any((each) => each.kind == ParameterKind.NAMED)) {
      return "Named parameters on message functions are not supported.";
    }
    var arguments = node.argumentList.arguments;
    var instance = _expectedInstance(node.methodName.name);
    return instance.checkValidity(node, arguments, name, parameters,
        nameAndArgsGenerated: generateNameAndArgs);
  }

  /// Record the parameters of the function or method declaration we last
  /// encountered before seeing the Intl.message call.
  void visitMethodDeclaration(MethodDeclaration node) {
    parameters = node.parameters;
    if (parameters == null) {
      parameters = new FormalParameterList(null, [], null, null, null);
    }
    name = node.name.name;
    super.visitMethodDeclaration(node);
  }

  /// Record the parameters of the function or method declaration we last
  /// encountered before seeing the Intl.message call.
  void visitFunctionDeclaration(FunctionDeclaration node) {
    parameters = node.functionExpression.parameters;
    if (parameters == null) {
      parameters = new FormalParameterList(null, [], null, null, null);
    }
    name = node.name.name;
    super.visitFunctionDeclaration(node);
  }

  /// Examine method invocations to see if they look like calls to Intl.message.
  /// If we've found one, stop recursing. This is important because we can have
  /// Intl.message(...Intl.plural...) and we don't want to treat the inner
  /// plural as if it was an outermost message.
  void visitMethodInvocation(MethodInvocation node) {
    if (!addIntlMessage(node)) {
      super.visitMethodInvocation(node);
    }
  }

  /// Check that the node looks like an Intl.message invocation, and create
  /// the [IntlMessage] object from it and store it in [messages]. Return true
  /// if we successfully extracted a message and should stop looking. Return
  /// false if we didn't, so should continue recursing.
  bool addIntlMessage(MethodInvocation node) {
    if (!looksLikeIntlMessage(node)) return false;
    var reason = checkValidity(node);
    if (reason != null) {
      if (!extraction.suppressWarnings) {
        var err = new StringBuffer()
          ..write("Skipping invalid Intl.message invocation\n    <$node>\n")
          ..writeAll(
              ["    reason: $reason\n", extraction._reportErrorLocation(node)]);
        var errString = err.toString();
        extraction.warnings.add(errString);
        extraction.onMessage(errString);
      }
      // We found one, but it's not valid. Stop recursing.
      return true;
    }
    var message;
    if (node.methodName.name == "message") {
      message = messageFromIntlMessageCall(node);
    } else {
      message = messageFromDirectPluralOrGenderCall(node);
    }
    if (message != null) messages[message.name] = message;
    return true;
  }

  /// Create a MainMessage from [node] using the name and
  /// parameters of the last function/method declaration we encountered,
  /// and the values we get by calling [extract]. We set those values
  /// by calling [setAttribute]. This is the common parts between
  /// [messageFromIntlMessageCall] and [messageFromDirectPluralOrGenderCall].
  MainMessage _messageFromNode(
      MethodInvocation node, Function extract, Function setAttribute) {
    var message = new MainMessage();
    message.sourcePosition = node.offset;
    message.endPosition = node.end;
    if (generateNameAndArgs) {
      // Always try for class_method if this is a class method and transforming.
      // It will be overwritten below if the message specifies it explicitly.
      message.name = Message.classPlusMethodName(node, name) ?? name;
    } else {
      message.name = name;
    }
    message.arguments =
        parameters.parameters.map((x) => x.identifier.name).toList();
    var arguments = node.argumentList.arguments;
    var extractionResult = extract(message, arguments);
    if (extractionResult == null) return null;

    for (NamedExpression namedArgument
        in arguments.where((x) => x is NamedExpression)) {
      var name = namedArgument.name.label.name;
      var exp = namedArgument.expression;
      var evaluator = new ConstantEvaluator();
      var basicValue = exp.accept(evaluator);
      var value = basicValue == ConstantEvaluator.NOT_A_CONSTANT
          ? exp.toString()
          : basicValue;
      setAttribute(message, name, value);
    }
    return message;
  }

  /// Create a MainMessage from [node] using the name and
  /// parameters of the last function/method declaration we encountered
  /// and the parameters to the Intl.message call.
  MainMessage messageFromIntlMessageCall(MethodInvocation node) {
    MainMessage extractFromIntlCall(MainMessage message, List arguments) {
      try {
        var interpolation = new InterpolationVisitor(message, extraction);
        arguments.first.accept(interpolation);
        if (interpolation.pieces.any((x) => x is Plural || x is Gender) &&
            !extraction.allowEmbeddedPluralsAndGenders) {
          if (interpolation.pieces.any((x) => x is String && x.isNotEmpty)) {
            throw new IntlMessageExtractionException(
                "Plural and gender expressions must be at the top level, "
                "they cannot be embedded in larger string literals.\n"
                "Error at $node");
          }
        }
        message.messagePieces.addAll(interpolation.pieces as List<Message>);
      } on IntlMessageExtractionException catch (e) {
        message = null;
        var err = new StringBuffer()
          ..writeAll(["Error ", e, "\nProcessing <", node, ">\n"])
          ..write(extraction._reportErrorLocation(node));
        var errString = err.toString();
        extraction.onMessage(errString);
        extraction.warnings.add(errString);
      }
      return message; // Because we may have set it to null on an error.
    }

    void setValue(MainMessage message, String fieldName, Object fieldValue) {
      message[fieldName] = fieldValue;
    }

    return _messageFromNode(node, extractFromIntlCall, setValue);
  }

  /// Create a MainMessage from [node] using the name and
  /// parameters of the last function/method declaration we encountered
  /// and the parameters to the Intl.plural or Intl.gender call.
  MainMessage messageFromDirectPluralOrGenderCall(MethodInvocation node) {
    MainMessage extractFromPluralOrGender(MainMessage message, _) {
      var visitor = new PluralAndGenderVisitor(
          message.messagePieces, message, extraction);
      node.accept(visitor);
      return message;
    }

    void setAttribute(MainMessage msg, String fieldName, fieldValue) {
      if (msg.attributeNames.contains(fieldName)) {
        msg[fieldName] = fieldValue;
      }
    }
    return _messageFromNode(node, extractFromPluralOrGender, setAttribute);
  }
}

/// Given an interpolation, find all of its chunks, validate that they are only
/// simple variable substitutions or else Intl.plural/gender calls,
/// and keep track of the pieces of text so that other parts
/// of the program can deal with the simple string sections and the generated
/// parts separately. Note that this is a SimpleAstVisitor, so it only
/// traverses one level of children rather than automatically recursing. If we
/// find a plural or gender, which requires recursion, we do it with a separate
/// special-purpose visitor.
class InterpolationVisitor extends SimpleAstVisitor {
  final Message message;

  /// The message extraction in which we are running.
  final MessageExtraction extraction;

  InterpolationVisitor(this.message, this.extraction);

  List pieces = [];
  String get extractedMessage => pieces.join();

  void visitAdjacentStrings(AdjacentStrings node) {
    node.visitChildren(this);
    super.visitAdjacentStrings(node);
  }

  void visitStringInterpolation(StringInterpolation node) {
    node.visitChildren(this);
    super.visitStringInterpolation(node);
  }

  void visitSimpleStringLiteral(SimpleStringLiteral node) {
    pieces.add(node.value);
    super.visitSimpleStringLiteral(node);
  }

  void visitInterpolationString(InterpolationString node) {
    pieces.add(node.value);
    super.visitInterpolationString(node);
  }

  void visitInterpolationExpression(InterpolationExpression node) {
    if (node.expression is SimpleIdentifier) {
      return handleSimpleInterpolation(node);
    } else {
      return lookForPluralOrGender(node);
    }
    // Note that we never end up calling super.
  }

  lookForPluralOrGender(InterpolationExpression node) {
    var visitor = new PluralAndGenderVisitor(pieces, message, extraction);
    node.accept(visitor);
    if (!visitor.foundPluralOrGender) {
      throw new IntlMessageExtractionException(
          "Only simple identifiers and Intl.plural/gender/select expressions "
          "are allowed in message "
          "interpolation expressions.\nError at $node");
    }
  }

  void handleSimpleInterpolation(InterpolationExpression node) {
    var index = arguments.indexOf(node.expression.toString());
    if (index == -1) {
      throw new IntlMessageExtractionException(
          "Cannot find argument ${node.expression}");
    }
    pieces.add(index);
  }

  List get arguments => message.arguments;
}

/// A visitor to extract information from Intl.plural/gender sends. Note that
/// this is a SimpleAstVisitor, so it doesn't automatically recurse. So this
/// needs to be called where we expect a plural or gender immediately below.
class PluralAndGenderVisitor extends SimpleAstVisitor {
  /// The message extraction in which we are running.
  final MessageExtraction extraction;

  /// A plural or gender always exists in the context of a parent message,
  /// which could in turn also be a plural or gender.
  final ComplexMessage parent;

  /// The pieces of the message. We are given an initial version of this
  /// from our parent and we add to it as we find additional information.
  List pieces;

  /// This will be set to true if we find a plural or gender.
  bool foundPluralOrGender = false;

  PluralAndGenderVisitor(this.pieces, this.parent, this.extraction) : super();

  visitInterpolationExpression(InterpolationExpression node) {
    // TODO(alanknight): Provide better errors for malformed expressions.
    if (!looksLikePluralOrGender(node.expression)) return;
    var reason = checkValidity(node.expression);
    if (reason != null) throw reason;
    var message = messageFromMethodInvocation(node.expression);
    foundPluralOrGender = true;
    pieces.add(message);
    super.visitInterpolationExpression(node);
  }

  visitMethodInvocation(MethodInvocation node) {
    pieces.add(messageFromMethodInvocation(node));
    super.visitMethodInvocation(node);
  }

  /// Return true if [node] matches the pattern for plural or gender message.
  bool looksLikePluralOrGender(MethodInvocation node) {
    if (!["plural", "gender", "select"].contains(node.methodName.name)) {
      return false;
    }
    if (!(node.target is SimpleIdentifier)) return false;
    SimpleIdentifier target = node.target;
    return target.token.toString() == "Intl";
  }

  /// Returns a String describing why the node is invalid, or null if no
  /// reason is found, so it's presumed valid.
  String checkValidity(MethodInvocation node) {
    // TODO(alanknight): Add reasonable validity checks.
    return null;
  }

  /// Create a MainMessage from [node] using the name and
  /// parameters of the last function/method declaration we encountered
  /// and the parameters to the Intl.message call.
  Message messageFromMethodInvocation(MethodInvocation node) {
    var message;
    switch (node.methodName.name) {
      case "gender":
        message = new Gender();
        break;
      case "plural":
        message = new Plural();
        break;
      case "select":
        message = new Select();
        break;
      default:
        throw new IntlMessageExtractionException(
            "Invalid plural/gender/select message");
    }
    message.parent = parent;

    var arguments = message.argumentsOfInterestFor(node);
    arguments.forEach((key, value) {
      try {
        var interpolation = new InterpolationVisitor(message, extraction);
        value.accept(interpolation);
        message[key] = interpolation.pieces;
      } on IntlMessageExtractionException catch (e) {
        message = null;
        var err = new StringBuffer()
          ..writeAll(["Error ", e, "\nProcessing <", node, ">"])
          ..write(extraction._reportErrorLocation(node));
        var errString = err.toString();
        extraction.onMessage(errString);
        extraction.warnings.add(errString);
      }
    });
    var mainArg = node.argumentList.arguments
        .firstWhere((each) => each is! NamedExpression);
    if (mainArg is SimpleStringLiteral) {
      message.mainArgument = mainArg.toString();
    } else if (mainArg is SimpleIdentifier) {
      message.mainArgument = mainArg.name;
    } else {
      var err = new StringBuffer()
        ..write("Error (Invalid argument to plural/gender/select, "
            "must be simple variable reference) "
            "\nProcessing <$node>")
        ..write(extraction._reportErrorLocation(node));
      var errString = err.toString();
      extraction.onMessage(errString);
      extraction.warnings.add(errString);
    }
    return message;
  }
}

/// Exception thrown when we cannot process a message properly.
class IntlMessageExtractionException implements Exception {
  /// A message describing the error.
  final String message;

  /// Creates a new exception with an optional error [message].
  const IntlMessageExtractionException([this.message = ""]);

  String toString() => "IntlMessageExtractionException: $message";
}
