// 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';

export 'package:analyzer/dart/ast/standard_ast_factory.dart';

final ast = AstBuilder();

class AstBuilder {
  KeywordToken get constKeyword => KeywordToken(Keyword.CONST, 0);

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

  FunctionTypeAlias functionTypeAlias(TypeName ret, SimpleIdentifier name,
      List<TypeParameter> tParams, List<FormalParameter> params) {
    TypeParameterList tps =
        (tParams.length == 0) ? null : typeParameterList(tParams);
    FormalParameterList fps = formalParameterList(params);
    Token semi = Token(TokenType.SEMICOLON, 0);
    Token td = KeywordToken(Keyword.TYPEDEF, 0);
    return astFactory.functionTypeAlias(
        null, null, td, ret, name, tps, fps, semi);
  }

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

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

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

  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.GT_GT_GT;
      case ">>>=":
        return TokenType.GT_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;
    }
  }

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

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

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

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

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

  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 = blockFunctionBody(b);
    return methodDeclaration(rt, m, fl, body, isStatic: isStatic);
  }

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

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

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

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

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

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

  FormalParameter optionalFormal(NormalFormalParameter fp) {
    return optionalFormalParameter(fp);
  }

  FormalParameter namedFormal(NormalFormalParameter fp) {
    return namedFormalParameter(fp);
  }

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

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

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

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

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

  ConstructorName constructorName(TypeName type, [SimpleIdentifier name]) {
    Token period = name != null ? Token(TokenType.PERIOD, 0) : null;
    return astFactory.constructorName(type, period, name);
  }

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  FormalParameter requiredFormalParameter(NormalFormalParameter fp) {
    return fp;
  }

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

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

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