// Copyright (c) 2015, 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 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/standard_ast_factory.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/src/dart/ast/token.dart';
import 'package:analyzer/src/generated/utilities_dart.dart';
import 'package:logging/logging.dart' as logger;

final _log = new logger.Logger('dev_compiler.ast_builder');

// Wrappers around constructors for the dart ast.  The AstBuilder class
// provides a higher-level interface, abstracting both from the lexical
// details and some of helper classes.  The RawAstBuilder class provides
// a low-level wrapper class (below) abstracts from the lexical details
// but otherwise faithfully mirrors the construction API.
class AstBuilder {
  static SimpleIdentifier identifierFromString(String name) {
    return RawAstBuilder.identifierFromString(name);
  }

  static PrefixedIdentifier prefixedIdentifier(
      SimpleIdentifier pre, SimpleIdentifier id) {
    return RawAstBuilder.prefixedIdentifier(pre, id);
  }

  static TypeParameter typeParameter(SimpleIdentifier name,
      [TypeName bound = null]) {
    return RawAstBuilder.typeParameter(name, bound);
  }

  static TypeParameterList typeParameterList(List<TypeParameter> params) {
    return RawAstBuilder.typeParameterList(params);
  }

  static TypeArgumentList typeArgumentList(List<TypeAnnotation> args) {
    return RawAstBuilder.typeArgumentList(args);
  }

  static ArgumentList argumentList(List<Expression> args) {
    return RawAstBuilder.argumentList(args);
  }

  static TypeName typeName(Identifier id, List<TypeAnnotation> args) {
    TypeArgumentList argList = null;
    if (args != null && args.length > 0) argList = typeArgumentList(args);
    return RawAstBuilder.typeName(id, argList);
  }

  static FunctionTypeAlias functionTypeAlias(
      TypeName ret,
      SimpleIdentifier name,
      List<TypeParameter> tParams,
      List<FormalParameter> params) {
    TypeParameterList tps =
        (tParams.length == 0) ? null : typeParameterList(tParams);
    FormalParameterList fps = formalParameterList(params);
    return RawAstBuilder.functionTypeAlias(ret, name, tps, fps);
  }

  static BooleanLiteral booleanLiteral(bool b) {
    return RawAstBuilder.booleanLiteral(b);
  }

  static NullLiteral nullLiteral() {
    return RawAstBuilder.nullLiteral();
  }

  static IntegerLiteral integerLiteral(int i) {
    return RawAstBuilder.integerLiteral(i);
  }

  static StringLiteral stringLiteral(String s) {
    return RawAstBuilder.simpleStringLiteral(s);
  }

  static StringLiteral multiLineStringLiteral(String s) {
    return RawAstBuilder.tripleQuotedStringLiteral(s);
  }

  static AsExpression asExpression(Expression exp, TypeName type) {
    return RawAstBuilder.asExpression(exp, type);
  }

  static IsExpression isExpression(Expression exp, TypeName type) {
    return RawAstBuilder.isExpression(exp, type);
  }

  static ParenthesizedExpression parenthesizedExpression(Expression exp) {
    return RawAstBuilder.parenthesizedExpression(exp);
  }

  static Expression parenthesize(Expression exp) {
    if (exp is Identifier ||
        exp is ParenthesizedExpression ||
        exp is FunctionExpressionInvocation ||
        exp is MethodInvocation) return exp;
    return parenthesizedExpression(exp);
  }

  static PropertyAccess propertyAccess(
      Expression target, SimpleIdentifier name) {
    var p = new Token(TokenType.PERIOD, 0);
    return astFactory.propertyAccess(target, p, name);
  }

  static MethodInvocation methodInvoke(Expression target, SimpleIdentifier name,
      TypeArgumentList typeArguments, NodeList<Expression> args) {
    var p = new Token(TokenType.PERIOD, 0);
    return astFactory.methodInvocation(
        target, p, name, typeArguments, argumentList(args));
  }

  static TokenType getTokenType(String lexeme) {
    switch (lexeme) {
      case "&":
        return TokenType.AMPERSAND;
      case "&&":
        return TokenType.AMPERSAND_AMPERSAND;
      case "&=":
        return TokenType.AMPERSAND_EQ;
      case "@":
        return TokenType.AT;
      case "!":
        return TokenType.BANG;
      case "!=":
        return TokenType.BANG_EQ;
      case "|":
        return TokenType.BAR;
      case "||":
        return TokenType.BAR_BAR;
      case "|=":
        return TokenType.BAR_EQ;
      case ":":
        return TokenType.COLON;
      case ",":
        return TokenType.COMMA;
      case "^":
        return TokenType.CARET;
      case "^=":
        return TokenType.CARET_EQ;
      case "}":
        return TokenType.CLOSE_CURLY_BRACKET;
      case ")":
        return TokenType.CLOSE_PAREN;
      case "]":
        return TokenType.CLOSE_SQUARE_BRACKET;
      case "=":
        return TokenType.EQ;
      case "==":
        return TokenType.EQ_EQ;
      case "=>":
        return TokenType.FUNCTION;
      case ">":
        return TokenType.GT;
      case ">=":
        return TokenType.GT_EQ;
      case ">>":
        return TokenType.GT_GT;
      case ">>=":
        return TokenType.GT_GT_EQ;
      case "#":
        return TokenType.HASH;
      case "[]":
        return TokenType.INDEX;
      case "[]=":
        return TokenType.INDEX_EQ;
      case "<":
        return TokenType.LT;
      case "<=":
        return TokenType.LT_EQ;
      case "<<":
        return TokenType.LT_LT;
      case "<<=":
        return TokenType.LT_LT_EQ;
      case "-":
        return TokenType.MINUS;
      case "-=":
        return TokenType.MINUS_EQ;
      case "--":
        return TokenType.MINUS_MINUS;
      case "{":
        return TokenType.OPEN_CURLY_BRACKET;
      case "(":
        return TokenType.OPEN_PAREN;
      case "[":
        return TokenType.OPEN_SQUARE_BRACKET;
      case "%":
        return TokenType.PERCENT;
      case "%=":
        return TokenType.PERCENT_EQ;
      case ".":
        return TokenType.PERIOD;
      case "..":
        return TokenType.PERIOD_PERIOD;
      case "+":
        return TokenType.PLUS;
      case "+=":
        return TokenType.PLUS_EQ;
      case "++":
        return TokenType.PLUS_PLUS;
      case "?":
        return TokenType.QUESTION;
      case ";":
        return TokenType.SEMICOLON;
      case "/":
        return TokenType.SLASH;
      case "/=":
        return TokenType.SLASH_EQ;
      case "*":
        return TokenType.STAR;
      case "*=":
        return TokenType.STAR_EQ;
      case "\${":
        return TokenType.STRING_INTERPOLATION_EXPRESSION;
      case "\$":
        return TokenType.STRING_INTERPOLATION_IDENTIFIER;
      case "~":
        return TokenType.TILDE;
      case "~/":
        return TokenType.TILDE_SLASH;
      case "~/=":
        return TokenType.TILDE_SLASH_EQ;
      case "`":
        return TokenType.BACKPING;
      case "\\":
        return TokenType.BACKSLASH;
      case "...":
        return TokenType.PERIOD_PERIOD_PERIOD;
      case "??":
        return TokenType.QUESTION_QUESTION;
      case "??=":
        return TokenType.QUESTION_QUESTION_EQ;
      default:
        return null;
    }
  }

  static Token _binaryOperation(String oper) {
    var type = getTokenType(oper);
    assert(type != null);
    return new Token(type, 0);
  }

  static BinaryExpression binaryExpression(
      Expression l, String oper, Expression r) {
    Token token = _binaryOperation(oper);
    return RawAstBuilder.binaryExpression(l, token, r);
  }

  static ConditionalExpression conditionalExpression(
      Expression cond, Expression tExp, Expression fExp) {
    return RawAstBuilder.conditionalExpression(cond, tExp, fExp);
  }

  static Expression application(Expression function, List<Expression> es) {
    ArgumentList args = argumentList(es);
    return RawAstBuilder.functionExpressionInvocation(function, args);
  }

  static FormalParameterList formalParameterList(List<FormalParameter> params) {
    return RawAstBuilder.formalParameterList(params);
  }

  static Block block(List<Statement> statements) {
    return RawAstBuilder.block(statements);
  }

  static MethodDeclaration blockMethodDeclaration(
      TypeName rt,
      SimpleIdentifier m,
      List<FormalParameter> params,
      List<Statement> statements,
      {bool isStatic: false}) {
    FormalParameterList fl = formalParameterList(params);
    Block b = block(statements);
    BlockFunctionBody body = RawAstBuilder.blockFunctionBody(b);
    return RawAstBuilder.methodDeclaration(rt, m, fl, body, isStatic: isStatic);
  }

  static FunctionDeclaration blockFunctionDeclaration(
      TypeName rt,
      SimpleIdentifier f,
      List<FormalParameter> params,
      List<Statement> statements) {
    FunctionExpression fexp = blockFunction(params, statements);
    return RawAstBuilder.functionDeclaration(rt, f, fexp);
  }

  static FunctionExpression blockFunction(
      List<FormalParameter> params, List<Statement> statements) {
    FormalParameterList fl = formalParameterList(params);
    Block b = block(statements);
    BlockFunctionBody body = RawAstBuilder.blockFunctionBody(b);
    return RawAstBuilder.functionExpression(fl, body);
  }

  static FunctionExpression expressionFunction(
      List<FormalParameter> params, Expression body,
      [bool decl = false]) {
    FormalParameterList fl = formalParameterList(params);
    ExpressionFunctionBody b = RawAstBuilder.expressionFunctionBody(body, decl);
    return RawAstBuilder.functionExpression(fl, b);
  }

  static FunctionDeclarationStatement functionDeclarationStatement(
      TypeName rType, SimpleIdentifier name, FunctionExpression fe) {
    var fd = RawAstBuilder.functionDeclaration(rType, name, fe);
    return RawAstBuilder.functionDeclarationStatement(fd);
  }

  static Statement returnExpression([Expression e]) {
    return RawAstBuilder.returnExpression(e);
  }

  // let b = e1 in e2 == (\b.e2)(e1)
  static Expression letExpression(
      FormalParameter b, Expression e1, Expression e2) {
    FunctionExpression l = expressionFunction(<FormalParameter>[b], e2);
    return application(parenthesize(l), <Expression>[e1]);
  }

  static SimpleFormalParameter simpleFormal(SimpleIdentifier v, TypeName t) {
    return RawAstBuilder.simpleFormalParameter(v, t);
  }

  static FunctionTypedFormalParameter functionTypedFormal(
      TypeName ret, SimpleIdentifier v, List<FormalParameter> params) {
    FormalParameterList ps = formalParameterList(params);
    return RawAstBuilder.functionTypedFormalParameter(ret, v, ps);
  }

  static FormalParameter requiredFormal(NormalFormalParameter fp) {
    return RawAstBuilder.requiredFormalParameter(fp);
  }

  static FormalParameter optionalFormal(NormalFormalParameter fp) {
    return RawAstBuilder.optionalFormalParameter(fp);
  }

  static FormalParameter namedFormal(NormalFormalParameter fp) {
    return RawAstBuilder.namedFormalParameter(fp);
  }

  static NamedExpression namedParameter(String s, Expression e) {
    return namedExpression(s, e);
  }

  static NamedExpression namedExpression(String s, Expression e) {
    return RawAstBuilder.namedExpression(identifierFromString(s), e);
  }

  /// Declares a single variable `var <name> = <init>` with the type and name
  /// specified by the VariableElement. See also [variableStatement].
  static VariableDeclarationList declareVariable(SimpleIdentifier name,
      [Expression init]) {
    var eqToken = init != null ? new Token(TokenType.EQ, 0) : null;
    var varToken = new KeywordToken(Keyword.VAR, 0);
    return astFactory.variableDeclarationList(null, null, varToken, null,
        [astFactory.variableDeclaration(name, eqToken, init)]);
  }

  static VariableDeclarationStatement variableStatement(SimpleIdentifier name,
      [Expression init]) {
    return RawAstBuilder
        .variableDeclarationStatement(declareVariable(name, init));
  }

  static InstanceCreationExpression instanceCreation(
      ConstructorName ctor, List<Expression> args) {
    var newToken = new KeywordToken(Keyword.NEW, 0);
    return astFactory.instanceCreationExpression(
        newToken, ctor, RawAstBuilder.argumentList(args));
  }
}

// This class provides a low-level wrapper around the constructors for
// the AST.  It mostly simply abstracts from the lexical tokens.
class RawAstBuilder {
  static ConstructorName constructorName(TypeName type,
      [SimpleIdentifier name]) {
    Token period = name != null ? new Token(TokenType.PERIOD, 0) : null;
    return astFactory.constructorName(type, period, name);
  }

  static SimpleIdentifier identifierFromString(String name) {
    StringToken token = new SyntheticStringToken(TokenType.IDENTIFIER, name, 0);
    return astFactory.simpleIdentifier(token);
  }

  static PrefixedIdentifier prefixedIdentifier(
      SimpleIdentifier pre, SimpleIdentifier id) {
    Token period = new Token(TokenType.PERIOD, 0);
    return astFactory.prefixedIdentifier(pre, period, id);
  }

  static TypeParameter typeParameter(SimpleIdentifier name,
      [TypeName bound = null]) {
    Token keyword =
        (bound == null) ? null : new KeywordToken(Keyword.EXTENDS, 0);
    return astFactory.typeParameter(null, null, name, keyword, bound);
  }

  static TypeParameterList typeParameterList(List<TypeParameter> params) {
    Token lb = new Token(TokenType.LT, 0);
    Token rb = new Token(TokenType.GT, 0);
    return astFactory.typeParameterList(lb, params, rb);
  }

  static TypeArgumentList typeArgumentList(List<TypeAnnotation> args) {
    Token lb = new Token(TokenType.LT, 0);
    Token rb = new Token(TokenType.GT, 0);
    return astFactory.typeArgumentList(lb, args, rb);
  }

  static ArgumentList argumentList(List<Expression> args) {
    Token lp = new BeginToken(TokenType.OPEN_PAREN, 0);
    Token rp = new Token(TokenType.CLOSE_PAREN, 0);
    return astFactory.argumentList(lp, args, rp);
  }

  static TypeName typeName(Identifier id, TypeArgumentList l) {
    return astFactory.typeName(id, l);
  }

  static FunctionTypeAlias functionTypeAlias(TypeName ret,
      SimpleIdentifier name, TypeParameterList tps, FormalParameterList fps) {
    Token semi = new Token(TokenType.SEMICOLON, 0);
    Token td = new KeywordToken(Keyword.TYPEDEF, 0);
    return astFactory.functionTypeAlias(
        null, null, td, ret, name, tps, fps, semi);
  }

  static BooleanLiteral booleanLiteral(bool b) {
    var k = new KeywordToken(b ? Keyword.TRUE : Keyword.FALSE, 0);
    return astFactory.booleanLiteral(k, b);
  }

  static NullLiteral nullLiteral() {
    var n = new KeywordToken(Keyword.NULL, 0);
    return astFactory.nullLiteral(n);
  }

  static IntegerLiteral integerLiteral(int i) {
    StringToken token = new StringToken(TokenType.INT, '$i', 0);
    return astFactory.integerLiteral(token, i);
  }

  static SimpleStringLiteral simpleStringLiteral(String s) {
    StringToken token = new StringToken(TokenType.STRING, "\"" + s + "\"", 0);
    return astFactory.simpleStringLiteral(token, s);
  }

  static SimpleStringLiteral tripleQuotedStringLiteral(String s) {
    StringToken token = new StringToken(TokenType.STRING, '"""' + s + '"""', 0);
    return astFactory.simpleStringLiteral(token, s);
  }

  static AsExpression asExpression(Expression exp, TypeName type) {
    Token token = new KeywordToken(Keyword.AS, 0);
    return astFactory.asExpression(exp, token, type);
  }

  static IsExpression isExpression(Expression exp, TypeName type) {
    Token token = new KeywordToken(Keyword.IS, 0);
    return astFactory.isExpression(exp, token, null, type);
  }

  static ParenthesizedExpression parenthesizedExpression(Expression exp) {
    Token lp = new BeginToken(TokenType.OPEN_PAREN, exp.offset);
    Token rp = new Token(TokenType.CLOSE_PAREN, exp.end);
    return astFactory.parenthesizedExpression(lp, exp, rp);
  }

  static BinaryExpression binaryExpression(
      Expression l, Token op, Expression r) {
    return astFactory.binaryExpression(l, op, r);
  }

  static ConditionalExpression conditionalExpression(
      Expression cond, Expression tExp, Expression fExp) {
    var q = new Token(TokenType.QUESTION, 0);
    var c = new Token(TokenType.COLON, 0);
    return astFactory.conditionalExpression(cond, q, tExp, c, fExp);
  }

  static Expression functionExpressionInvocation(
      Expression function, ArgumentList es) {
    return astFactory.functionExpressionInvocation(function, null, es);
  }

  static FormalParameterList formalParameterList(List<FormalParameter> params) {
    Token lp = new BeginToken(TokenType.OPEN_PAREN, 0);
    Token rp = new Token(TokenType.CLOSE_PAREN, 0);
    bool hasOptional = params.any((p) => p.kind == ParameterKind.POSITIONAL);
    bool hasNamed = params.any((p) => p.kind == ParameterKind.NAMED);
    assert(!(hasOptional && hasNamed));
    Token ld = null;
    Token rd = null;
    if (hasOptional) {
      ld = new BeginToken(TokenType.OPEN_SQUARE_BRACKET, 0);
      rd = new Token(TokenType.CLOSE_SQUARE_BRACKET, 0);
    }
    if (hasNamed) {
      ld = new BeginToken(TokenType.OPEN_CURLY_BRACKET, 0);
      rd = new Token(TokenType.CLOSE_CURLY_BRACKET, 0);
    }
    return astFactory.formalParameterList(lp, params, ld, rd, rp);
  }

  static Block block(List<Statement> statements) {
    Token ld = new BeginToken(TokenType.OPEN_CURLY_BRACKET, 0);
    Token rd = new Token(TokenType.CLOSE_CURLY_BRACKET, 0);
    return astFactory.block(ld, statements, rd);
  }

  static BlockFunctionBody blockFunctionBody(Block b) {
    return astFactory.blockFunctionBody(null, null, b);
  }

  static ExpressionFunctionBody expressionFunctionBody(Expression body,
      [bool decl = false]) {
    Token semi = (decl) ? new Token(TokenType.SEMICOLON, 0) : null;
    return astFactory.expressionFunctionBody(null, null, body, semi);
  }

  static ExpressionStatement expressionStatement(Expression expression) {
    Token semi = new Token(TokenType.SEMICOLON, 0);
    return astFactory.expressionStatement(expression, semi);
  }

  static FunctionDeclaration functionDeclaration(
      TypeName rt, SimpleIdentifier f, FunctionExpression fexp) {
    return astFactory.functionDeclaration(null, null, null, rt, null, f, fexp);
  }

  static MethodDeclaration methodDeclaration(TypeName rt, SimpleIdentifier m,
      FormalParameterList fl, FunctionBody body,
      {bool isStatic: false}) {
    Token st = isStatic ? new KeywordToken(Keyword.STATIC, 0) : null;
    return astFactory.methodDeclaration(
        null, null, null, st, rt, null, null, m, null, fl, body);
  }

  static FunctionExpression functionExpression(
      FormalParameterList fl, FunctionBody body) {
    return astFactory.functionExpression(null, fl, body);
  }

  static FunctionDeclarationStatement functionDeclarationStatement(
      FunctionDeclaration fd) {
    return astFactory.functionDeclarationStatement(fd);
  }

  static Statement returnExpression([Expression e]) {
    Token ret = new KeywordToken(Keyword.RETURN, 0);
    Token semi = new Token(TokenType.SEMICOLON, 0);
    return astFactory.returnStatement(ret, e, semi);
  }

  static SimpleFormalParameter simpleFormalParameter(
      SimpleIdentifier v, TypeName t) {
    return astFactory.simpleFormalParameter(null, <Annotation>[], null, t, v);
  }

  static FunctionTypedFormalParameter functionTypedFormalParameter(
      TypeName ret, SimpleIdentifier v, FormalParameterList ps) {
    return astFactory.functionTypedFormalParameter(
        null, <Annotation>[], ret, v, null, ps);
  }

  static FormalParameter requiredFormalParameter(NormalFormalParameter fp) {
    return fp;
  }

  static FormalParameter optionalFormalParameter(NormalFormalParameter fp) {
    return astFactory.defaultFormalParameter(
        fp, ParameterKind.POSITIONAL, null, null);
  }

  static FormalParameter namedFormalParameter(NormalFormalParameter fp) {
    return astFactory.defaultFormalParameter(
        fp, ParameterKind.NAMED, null, null);
  }

  static NamedExpression namedParameter(SimpleIdentifier s, Expression e) {
    return namedExpression(s, e);
  }

  static NamedExpression namedExpression(SimpleIdentifier s, Expression e) {
    Label l = astFactory.label(s, new Token(TokenType.COLON, 0));
    return astFactory.namedExpression(l, e);
  }

  static VariableDeclarationStatement variableDeclarationStatement(
      VariableDeclarationList varDecl) {
    var semi = new Token(TokenType.SEMICOLON, 0);
    return astFactory.variableDeclarationStatement(varDecl, semi);
  }
}
