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

part of js;

class TemplateManager {
  Map<String, Template> expressionTemplates = new Map<String, Template>();
  Map<String, Template> statementTemplates = new Map<String, Template>();

  TemplateManager();


  Template lookupExpressionTemplate(String source) {
    return expressionTemplates[source];
  }

  Template defineExpressionTemplate(String source, Node ast) {
    Template template =
        new Template(source, ast, isExpression: true, forceCopy: false);
    expressionTemplates[source] = template;
    return template;
  }

  Template lookupStatementTemplate(String source) {
    return statementTemplates[source];
  }

  Template defineStatementTemplate(String source, Node ast) {
    Template template =
        new Template(source, ast, isExpression: false, forceCopy: false);
    statementTemplates[source] = template;
    return template;
  }
}

/**
 * A Template is created with JavaScript AST containing placeholders (interface
 * InterpolatedNode).  The [instantiate] method creates an AST that looks like
 * the original with the placeholders replaced by the arguments to
 * [instantiate].
 */
class Template {
  final String source;
  final bool isExpression;
  final bool forceCopy;
  final Node ast;

  Instantiator instantiator;

  int positionalArgumentCount = -1;

  // Null, unless there are named holes.
  List<String> holeNames;
  bool get isPositional => holeNames == null;

  Template(this.source, this.ast,
           {this.isExpression: true, this.forceCopy: false}) {
    _compile();
  }

  Template.withExpressionResult(this.ast)
      : source = null, isExpression = true, forceCopy = false {
    assert(ast is Expression);
    assert(_checkNoPlaceholders());
    positionalArgumentCount = 0;
    instantiator = (arguments) => ast;
  }

  Template.withStatementResult(this.ast)
      : source = null, isExpression = false, forceCopy = false {
    assert(ast is Statement);
    assert(_checkNoPlaceholders());
    positionalArgumentCount = 0;
    instantiator = (arguments) => ast;
  }

  bool _checkNoPlaceholders() {
    InstantiatorGeneratorVisitor generator =
        new InstantiatorGeneratorVisitor(false);
    generator.compile(ast);
    return generator.analysis.count == 0;
  }

  void _compile() {
    InstantiatorGeneratorVisitor generator =
        new InstantiatorGeneratorVisitor(forceCopy);
    instantiator = generator.compile(ast);
    positionalArgumentCount = generator.analysis.count;
    Set<String> names = generator.analysis.holeNames;
    holeNames = names.toList(growable:false);
  }

  /// Instantiates the template with the given [arguments].
  ///
  /// This method fills in the holes with the given arguments. The [arguments]
  /// must be either a [List] or a [Map].
  Node instantiate(var arguments) {
    if (arguments is List) {
      if (arguments.length != positionalArgumentCount) {
        throw 'Wrong number of template arguments, given ${arguments.length}, '
            'expected $positionalArgumentCount';
      }
      return instantiator(arguments);
    }
    assert(arguments is Map);
    if (holeNames.length < arguments.length) {
      // This search is in O(n), but we only do it in case of an error, and the
      // number of holes should be quite limited.
      String unusedNames =
          arguments.keys.where((name) => !holeNames.contains(name)).join(", ");
      throw "Template arguments has unused mappings: $unusedNames";
    }
    if (!holeNames.every((String name) => arguments.containsKey(name))) {
      String notFound =
          holeNames.where((name) => !arguments.containsKey(name)).join(", ");
      throw "Template arguments is missing mappings for: $notFound";
    }
    return instantiator(arguments);
  }
}

/**
 * An Instantiator is a Function that generates a JS AST tree or List of
 * trees. [arguments] is a List for positional templates, or Map for
 * named templates.
 */
typedef Node Instantiator(var arguments);


/**
 * InstantiatorGeneratorVisitor compiles a template.  This class compiles a tree
 * containing [InterpolatedNode]s into a function that will create a copy of the
 * tree with the interpolated nodes substituted with provided values.
 */
class InstantiatorGeneratorVisitor implements NodeVisitor<Instantiator> {

  final bool forceCopy;

  InterpolatedNodeAnalysis analysis = new InterpolatedNodeAnalysis();

  /**
   * The entire tree is cloned if [forceCopy] is true.
   */
  InstantiatorGeneratorVisitor(this.forceCopy);

  Instantiator compile(Node node) {
    analysis.visit(node);
    Instantiator result = visit(node);
    return result;
  }

  static error(String message) {
    throw message;
  }

  static Instantiator same(Node node) => (arguments) => node;
  static Node makeNull(arguments) => null;

  Instantiator visit(Node node) {
    if (forceCopy || analysis.containsInterpolatedNodes(node)) {
      return node.accept(this);
    }
    return same(node);
  }

  Instantiator visitNullable(Node node) {
    if (node == null) return makeNull;
    return visit(node);
  }

  Instantiator visitSplayable(Node node) {
    // TODO(sra): Process immediate [InterpolatedNode]s, permitting splaying.
    return visit(node);
  }

  Instantiator visitNode(Node node) {
    throw 'Unimplemented InstantiatorGeneratorVisitor for $node';
  }

  static RegExp identiferRE = new RegExp(r'^[A-Za-z_$][A-Za-z_$0-9]*$');

  static Expression convertStringToVariableUse(String value) {
    assert(identiferRE.hasMatch(value));
    return new VariableUse(value);
  }

  Instantiator visitInterpolatedExpression(InterpolatedExpression node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Expression) return value;
      if (value is String) return convertStringToVariableUse(value);
      error('Interpolated value #$nameOrPosition is not an Expression: $value');
    };
  }

  Instantiator visitSplayableExpression(Node node) {
    if (node is InterpolatedExpression) {
      var nameOrPosition = node.nameOrPosition;
      return (arguments) {
        var value = arguments[nameOrPosition];
        Expression toExpression(item) {
          if (item is Expression) return item;
          if (item is String) return convertStringToVariableUse(item);
          return error('Interpolated value #$nameOrPosition is not '
              'an Expression or List of Expressions: $value');
        }
        if (value is Iterable) return value.map(toExpression);
        return toExpression(value);
      };
    }
    return visit(node);
  }

  Instantiator visitInterpolatedLiteral(InterpolatedLiteral node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Literal) return value;
      error('Interpolated value #$nameOrPosition is not a Literal: $value');
    };
  }

  Instantiator visitInterpolatedParameter(InterpolatedParameter node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];

      Parameter toParameter(item) {
        if (item is Parameter) return item;
        if (item is String) return new Parameter(item);
        return error('Interpolated value #$nameOrPosition is not a Parameter or'
                     ' List of Parameters: $value');
      }
      if (value is Iterable) return value.map(toParameter);
      return toParameter(value);
    };
  }

  Instantiator visitInterpolatedSelector(InterpolatedSelector node) {
    // A selector is an expression, as in `a[selector]`.
    // A String argument converted into a LiteralString, so `a.#` with argument
    // 'foo' generates `a["foo"]` which prints as `a.foo`.
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Expression) return value;
      if (value is String) return new LiteralString('"$value"');
      error('Interpolated value #$nameOrPosition is not a selector: $value');
    };
  }

  Instantiator visitInterpolatedStatement(InterpolatedStatement node) {
    var nameOrPosition = node.nameOrPosition;
    return (arguments) {
      var value = arguments[nameOrPosition];
      if (value is Node) return value.toStatement();
      error('Interpolated value #$nameOrPosition is not a Statement: $value');
    };
  }

  Instantiator visitSplayableStatement(Node node) {
    if (node is InterpolatedStatement) {
      var nameOrPosition = node.nameOrPosition;
      return (arguments) {
        var value = arguments[nameOrPosition];
        Statement toStatement(item) {
          if (item is Statement) return item;
          if (item is Expression) return item.toStatement();;
          return error('Interpolated value #$nameOrPosition is not '
                       'a Statement or List of Statements: $value');
        }
        if (value is Iterable) return value.map(toStatement);
        return toStatement(value);
      };
    }
    return visit(node);
  }

  Instantiator visitProgram(Program node) {
    List instantiators = node.body.map(visitSplayableStatement).toList();
    return (arguments) {
      List<Statement> statements = <Statement>[];
      void add(node) {
        if (node is EmptyStatement) return;
        if (node is Iterable) {
          statements.addAll(node);
        } else {
          statements.add(node.toStatement());
        }
      }
      for (Instantiator instantiator in instantiators) {
        add(instantiator(arguments));
      }
      return new Program(statements);
    };
  }

  Instantiator visitBlock(Block node) {
    List instantiators = node.statements.map(visitSplayableStatement).toList();
    return (arguments) {
      List<Statement> statements = <Statement>[];
      void add(node) {
        if (node is EmptyStatement) return;
        if (node is Iterable) {
          statements.addAll(node);
        } else if (node is Block) {
          statements.addAll(node.statements);
        } else {
          statements.add(node.toStatement());
        }
      }
      for (Instantiator instantiator in instantiators) {
        add(instantiator(arguments));
      }
      return new Block(statements);
    };
  }

  Instantiator visitExpressionStatement(ExpressionStatement node) {
    Instantiator buildExpression = visit(node.expression);
    return (arguments) {
      return buildExpression(arguments).toStatement();
    };
  }

  Instantiator visitEmptyStatement(EmptyStatement node) =>
      (arguments) => new EmptyStatement();

  Instantiator visitIf(If node) {
    if (node.condition is InterpolatedExpression) {
      return visitIfConditionalCompilation(node);
    } else {
      return visitIfNormal(node);
    }
  }

  Instantiator visitIfConditionalCompilation(If node) {
    // Special version of visitInterpolatedExpression that permits bools.
    compileCondition(InterpolatedExpression node) {
      var nameOrPosition = node.nameOrPosition;
      return (arguments) {
        var value = arguments[nameOrPosition];
        if (value is bool) return value;
        if (value is Expression) return value;
        if (value is String) return convertStringToVariableUse(value);;
        error('Interpolated value #$nameOrPosition '
              'is not an Expression: $value');
      };
    }
    var makeCondition = compileCondition(node.condition);
    Instantiator makeThen = visit(node.then);
    Instantiator makeOtherwise = visit(node.otherwise);
    return (arguments) {
      var condition = makeCondition(arguments);
      if (condition is bool) {
        if (condition == true) {
          return makeThen(arguments);
        } else {
          return makeOtherwise(arguments);
        }
      }
      return new If(
          condition,
          makeThen(arguments),
          makeOtherwise(arguments));
    };
  }

  Instantiator visitIfNormal(If node) {
    Instantiator makeCondition = visit(node.condition);
    Instantiator makeThen = visit(node.then);
    Instantiator makeOtherwise = visit(node.otherwise);
    return (arguments) {
      return new If(
          makeCondition(arguments),
          makeThen(arguments),
          makeOtherwise(arguments));
    };
  }

  Instantiator visitFor(For node) {
    Instantiator makeInit = visitNullable(node.init);
    Instantiator makeCondition = visitNullable(node.condition);
    Instantiator makeUpdate = visitNullable(node.update);
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return new For(
          makeInit(arguments), makeCondition(arguments), makeUpdate(arguments),
          makeBody(arguments));
    };
  }

  Instantiator visitForIn(ForIn node) {
    Instantiator makeLeftHandSide = visit(node.leftHandSide);
    Instantiator makeObject = visit(node.object);
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return new ForIn(
          makeLeftHandSide(arguments),
          makeObject(arguments),
          makeBody(arguments));
    };
  }

  TODO(String name) {
    throw new UnimplementedError('$this.$name');
  }

  Instantiator visitWhile(While node) {
    Instantiator makeCondition = visit(node.condition);
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return new While(makeCondition(arguments), makeBody(arguments));
    };
  }

  Instantiator visitDo(Do node) {
    Instantiator makeBody = visit(node.body);
    Instantiator makeCondition = visit(node.condition);
    return (arguments) {
      return new Do(makeBody(arguments), makeCondition(arguments));
    };
  }

  Instantiator visitContinue(Continue node) =>
      (arguments) => new Continue(node.targetLabel);

  Instantiator visitBreak(Break node) =>
      (arguments) => new Break(node.targetLabel);

  Instantiator visitReturn(Return node) {
    Instantiator makeExpression = visitNullable(node.value);
    return (arguments) => new Return(makeExpression(arguments));
  }

  Instantiator visitThrow(Throw node) {
    Instantiator makeExpression = visit(node.expression);
    return (arguments) => new Throw(makeExpression(arguments));
  }

  Instantiator visitTry(Try node) {
    Instantiator makeBody = visit(node.body);
    Instantiator makeCatch = visitNullable(node.catchPart);
    Instantiator makeFinally = visitNullable(node.finallyPart);
    return (arguments) => new Try(
        makeBody(arguments), makeCatch(arguments), makeFinally(arguments));
  }

  Instantiator visitCatch(Catch node) {
    Instantiator makeDeclaration = visit(node.declaration);
    Instantiator makeBody = visit(node.body);
    return (arguments) => new Catch(
        makeDeclaration(arguments), makeBody(arguments));
  }

  Instantiator visitSwitch(Switch node) {
    Instantiator makeKey = visit(node.key);
    Iterable<Instantiator> makeCases = node.cases.map(visit);
    return (arguments) {
      return new Switch(makeKey(arguments),
          makeCases.map((Instantiator makeCase) => makeCase(arguments))
                   .toList());
    };
  }

  Instantiator visitCase(Case node) {
    Instantiator makeExpression = visit(node.expression);
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return new Case(makeExpression(arguments), makeBody(arguments));
    };
  }

  Instantiator visitDefault(Default node) {
    Instantiator makeBody = visit(node.body);
    return (arguments) {
      return new Default(makeBody(arguments));
    };
  }

  Instantiator visitFunctionDeclaration(FunctionDeclaration node) {
    Instantiator makeName = visit(node.name);
    Instantiator makeFunction = visit(node.function);
    return (arguments) =>
        new FunctionDeclaration(makeName(arguments), makeFunction(arguments));
  }

  Instantiator visitLabeledStatement(LabeledStatement node) =>
      TODO('visitLabeledStatement');
  Instantiator visitLiteralStatement(LiteralStatement node) =>
      TODO('visitLiteralStatement');
  Instantiator visitBlob(Blob node) =>
      TODO('visitBlob');
  Instantiator visitLiteralExpression(LiteralExpression node) =>
      TODO('visitLiteralExpression');

  Instantiator visitVariableDeclarationList(VariableDeclarationList node) {
    List<Instantiator> declarationMakers =
        node.declarations.map(visit).toList();
    return (arguments) {
      List<VariableInitialization> declarations = <VariableInitialization>[];
      for (Instantiator instantiator in declarationMakers) {
        var result = instantiator(arguments);
        declarations.add(result);
      }
      return new VariableDeclarationList(declarations);
    };
  }

  Instantiator visitAssignment(Assignment node) {
    Instantiator makeLeftHandSide = visit(node.leftHandSide);
    String op = node.op;
    Instantiator makeValue = visitNullable(node.value);
    return (arguments) {
      return new Assignment.compound(
          makeLeftHandSide(arguments),
          op,
          makeValue(arguments));
    };
  }

  Instantiator visitVariableInitialization(VariableInitialization node) {
    Instantiator makeDeclaration = visit(node.declaration);
    Instantiator makeValue = visitNullable(node.value);
    return (arguments) {
      return new VariableInitialization(
          makeDeclaration(arguments), makeValue(arguments));
    };
  }

  Instantiator visitConditional(Conditional cond) {
    Instantiator makeCondition = visit(cond.condition);
    Instantiator makeThen = visit(cond.then);
    Instantiator makeOtherwise = visit(cond.otherwise);
    return (arguments) => new Conditional(
        makeCondition(arguments),
        makeThen(arguments),
        makeOtherwise(arguments));
  }

  Instantiator visitNew(New node) =>
      handleCallOrNew(node, (target, arguments) => new New(target, arguments));

  Instantiator visitCall(Call node) =>
      handleCallOrNew(node, (target, arguments) => new Call(target, arguments));

  Instantiator handleCallOrNew(Call node, finish(target, arguments)) {
    Instantiator makeTarget = visit(node.target);
    Iterable<Instantiator> argumentMakers =
        node.arguments.map(visitSplayableExpression).toList();

    // TODO(sra): Avoid copying call arguments if no interpolation or forced
    // copying.
    return (arguments) {
      Node target = makeTarget(arguments);
      List<Expression> callArguments = <Expression>[];
      for (Instantiator instantiator in argumentMakers) {
        var result = instantiator(arguments);
        if (result is Iterable) {
          callArguments.addAll(result);
        } else {
          callArguments.add(result);
        }
      }
      return finish(target, callArguments.toList(growable: false));
    };
  }

  Instantiator visitBinary(Binary node) {
    Instantiator makeLeft = visit(node.left);
    Instantiator makeRight = visit(node.right);
    String op = node.op;
    return (arguments) =>
        new Binary(op, makeLeft(arguments), makeRight(arguments));
  }

  Instantiator visitPrefix(Prefix node) {
    Instantiator makeOperand = visit(node.argument);
    String op = node.op;
    return (arguments) => new Prefix(op, makeOperand(arguments));
  }

  Instantiator visitPostfix(Postfix node) {
    Instantiator makeOperand = visit(node.argument);
    String op = node.op;
    return (arguments) => new Postfix(op, makeOperand(arguments));
  }

  Instantiator visitVariableUse(VariableUse node) =>
      (arguments) => new VariableUse(node.name);

  Instantiator visitThis(This node) => (arguments) => new This();

  Instantiator visitVariableDeclaration(VariableDeclaration node) =>
      (arguments) => new VariableDeclaration(node.name);

  Instantiator visitParameter(Parameter node) =>
      (arguments) => new Parameter(node.name);

  Instantiator visitAccess(PropertyAccess node) {
    Instantiator makeReceiver = visit(node.receiver);
    Instantiator makeSelector = visit(node.selector);
    return (arguments) =>
        new PropertyAccess(makeReceiver(arguments), makeSelector(arguments));
  }

  Instantiator visitNamedFunction(NamedFunction node) {
    Instantiator makeDeclaration = visit(node.name);
    Instantiator makeFunction = visit(node.function);
    return (arguments) =>
        new NamedFunction(makeDeclaration(arguments), makeFunction(arguments));
  }

  Instantiator visitFun(Fun node) {
    List<Instantiator> paramMakers = node.params.map(visitSplayable).toList();
    Instantiator makeBody = visit(node.body);
    // TODO(sra): Avoid copying params if no interpolation or forced copying.
    return (arguments) {
      List<Parameter> params = <Parameter>[];
      for (Instantiator instantiator in paramMakers) {
        var result = instantiator(arguments);
        if (result is Iterable) {
          params.addAll(result);
        } else {
          params.add(result);
        }
      }
      Statement body = makeBody(arguments);
      return new Fun(params, body);
    };
  }

  Instantiator visitLiteralBool(LiteralBool node) =>
      (arguments) => new LiteralBool(node.value);

  Instantiator visitLiteralString(LiteralString node) =>
      (arguments) => new LiteralString(node.value);

  Instantiator visitLiteralNumber(LiteralNumber node) =>
      (arguments) => new LiteralNumber(node.value);

  Instantiator visitLiteralNull(LiteralNull node) =>
      (arguments) => new LiteralNull();

  Instantiator visitArrayInitializer(ArrayInitializer node) {
    // TODO(sra): Implement splicing?
    List<Instantiator> elementMakers = node.elements
        .map(visit)
        .toList(growable: false);
    return (arguments) {
      List<Expression> elements = elementMakers
          .map((Instantiator instantiator) => instantiator(arguments))
          .toList(growable: false);
      return new ArrayInitializer(elements);
    };
  }

  Instantiator visitArrayHole(ArrayHole node) {
    return (arguments) => new ArrayHole();
  }

  Instantiator visitObjectInitializer(ObjectInitializer node) {
    List<Instantiator> propertyMakers =
        node.properties.map(visitSplayable).toList();
    bool isOneLiner = node.isOneLiner;
    return (arguments) {
      List<Property> properties = <Property>[];
      for (Instantiator instantiator in propertyMakers) {
        var result = instantiator(arguments);
        if (result is Iterable) {
          properties.addAll(result);
        } else {
          properties.add(result);
        }
      }
      return new ObjectInitializer(properties, isOneLiner: isOneLiner);
    };
  }

  Instantiator visitProperty(Property node) {
    Instantiator makeName = visit(node.name);
    Instantiator makeValue = visit(node.value);
    return (arguments) {
      return new Property(makeName(arguments), makeValue(arguments));
    };
  }

  Instantiator visitRegExpLiteral(RegExpLiteral node) =>
      (arguments) => new RegExpLiteral(node.pattern);

  Instantiator visitComment(Comment node) => TODO('visitComment');

  Instantiator visitAwait(Await node) {
    Instantiator makeExpression = visit(node.expression);
    return (arguments) {
      return new Await(makeExpression(arguments));
    };
  }
}

/**
 * InterpolatedNodeAnalysis extract [InterpolatedNode]s from AST.
 */
class InterpolatedNodeAnalysis extends BaseVisitor {
  final Setlet<Node> containsInterpolatedNode = new Setlet<Node>();
  final List<InterpolatedNode> interpolatedNodes = <InterpolatedNode>[];
  final Setlet<String> holeNames = new Setlet<String>();
  int count = 0;

  InterpolatedNodeAnalysis();

  bool containsInterpolatedNodes(Node node) =>
      containsInterpolatedNode.contains(node);

  void visit(Node node) {
    node.accept(this);
  }

  void visitNode(Node node) {
    int before = count;
    node.visitChildren(this);
    if (count != before) containsInterpolatedNode.add(node);
    return null;
  }

  visitInterpolatedNode(InterpolatedNode node) {
    interpolatedNodes.add(node);
    containsInterpolatedNode.add(node);
    if (node.isNamed) holeNames.add(node.nameOrPosition);
    ++count;
  }
}
