/*
   * Generate AST initializers for any declared states, as well as any event
   * initializers for states.
   */
  private StatementListNode genStateInitializersAST(
      StatesModel model,
      NodeFactory nodeFactory,
      HashSet<String> configNamespaces,
      boolean generateDocComments,
      StatementListNode statementList) {
    StatementListNode result = statementList;
    Set<String> states = model.info.getStateNames();
    int count = 0;
    for (Iterator<String> iter = states.iterator(); iter.hasNext(); ) {
      State state = (State) model.stateByName((String) iter.next());
      if (state != null) {
        String identifier = state.getId().intern();
        IdentifierNode stateIdentifier = nodeFactory.identifier(identifier, false);
        IdentifierNode statesIdentifier = nodeFactory.identifier(STATES, false);

        LiteralNumberNode numberNode = nodeFactory.literalNumber(count);
        ArgumentListNode getIndexArgList = nodeFactory.argumentList(null, numberNode);
        GetExpressionNode getIndexExpression = nodeFactory.getExpression(getIndexArgList);
        getIndexExpression.setMode(Tokens.LEFTBRACKET_TOKEN);

        GetExpressionNode getStatesExpression = nodeFactory.getExpression(statesIdentifier);
        MemberExpressionNode base = nodeFactory.memberExpression(null, getStatesExpression);

        MemberExpressionNode getExpr = nodeFactory.memberExpression(base, getIndexExpression);

        // Declaration initializer
        if (state.isDeclared()) {
          ArgumentListNode argList = nodeFactory.argumentList(null, getExpr);
          SetExpressionNode selector = nodeFactory.setExpression(stateIdentifier, argList, false);
          MemberExpressionNode outer = nodeFactory.memberExpression(null, selector);
          ListNode list = nodeFactory.list(null, outer);
          ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
          result = nodeFactory.statementList(result, expressionStatement);
        }

        // Event handlers
        for (Iterator<Initializer> initializers = state.getEvents(); initializers.hasNext(); ) {
          EventInitializer ei = (EventInitializer) initializers.next();
          IdentifierNode addEventIdentifier = nodeFactory.identifier(ADDEVENTLISTENER, false);
          LiteralStringNode eventName = nodeFactory.literalString(ei.getName());
          macromedia.asc.parser.Node valueNode =
              ei.generateValueExpr(nodeFactory, configNamespaces, generateDocComments);
          ArgumentListNode addEventArgs = nodeFactory.argumentList(null, eventName);
          addEventArgs = nodeFactory.argumentList(addEventArgs, valueNode);

          CallExpressionNode addListener =
              (CallExpressionNode) nodeFactory.callExpression(addEventIdentifier, addEventArgs);
          addListener.setRValue(false);
          MemberExpressionNode outer = nodeFactory.memberExpression(getExpr, addListener);
          ListNode list = nodeFactory.list(null, outer);
          ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
          result = nodeFactory.statementList(result, expressionStatement);
        }
      }
      count++;
    }
    return result;
  }
  /*
   * Generates the initializers (AST) for all values that are shared between states (e.g. all instance factories
   * shared by AddItems overrides).
   */
  private StatementListNode genSharedFactoriesAST(
      StatesModel model, NodeFactory nodeFactory, StatementListNode statementList) {
    Map<String, SharedObject> shared = model.sharedObjects;

    StatementListNode result = statementList;

    for (Iterator<String> iter = shared.keySet().iterator(); iter.hasNext(); ) {
      SharedObject symbol = shared.get(iter.next());

      String varName = ((String) symbol.name + _FACTORY).intern();
      String typeName = NameFormatter.retrieveClassName(DEFERREDINSTANCEFROMFUNCTION);
      String factory = symbol.name + (symbol.model.isDeclared() ? _I : _C);
      String resetFunc = symbol.name + _R;

      MemberExpressionNode memberExpression =
          AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, factory, true);

      ArgumentListNode callExpressionArgumentList =
          nodeFactory.argumentList(null, memberExpression);

      if (symbol.model.getIsTransient()) {
        memberExpression =
            AbstractSyntaxTreeUtil.generateGetterSelector(nodeFactory, resetFunc, true);
        callExpressionArgumentList =
            nodeFactory.argumentList(callExpressionArgumentList, memberExpression);
      }

      QualifiedIdentifierNode qualifiedIdentifier =
          AbstractSyntaxTreeUtil.generateQualifiedIdentifier(
              nodeFactory, standardDefs.getCorePackage(), typeName, false);

      CallExpressionNode callExpression =
          (CallExpressionNode)
              nodeFactory.callExpression(qualifiedIdentifier, callExpressionArgumentList);
      callExpression.is_new = true;
      callExpression.setRValue(false);

      MemberExpressionNode ad = nodeFactory.memberExpression(null, callExpression);

      VariableDefinitionNode variableDefinition =
          AbstractSyntaxTreeUtil.generateVariable(nodeFactory, varName, typeName, false, ad);
      result = nodeFactory.statementList(result, variableDefinition);
    }
    return result;
  }
  /*
   * Generate all AST calls to instantiate itemCreationPolicy='immediate' nodes.
   */
  private StatementListNode genImmediateInitsAST(
      StatesModel model, NodeFactory nodeFactory, StatementListNode statementList) {
    StatementListNode result = statementList;
    List<String> objects = model.earlyInitObjects;

    for (Iterator<String> iter = objects.iterator(); iter.hasNext(); ) {
      String symbol = iter.next();
      String identifier = ((String) symbol + "_factory").intern();
      IdentifierNode idNode = nodeFactory.identifier(identifier, false);
      GetExpressionNode getIndexExpression = nodeFactory.getExpression(idNode);
      MemberExpressionNode base = nodeFactory.memberExpression(null, getIndexExpression);

      IdentifierNode getNode = nodeFactory.identifier(GETINSTANCE, false);

      CallExpressionNode selector = (CallExpressionNode) nodeFactory.callExpression(getNode, null);
      selector.setRValue(false);

      MemberExpressionNode memberExpression = nodeFactory.memberExpression(base, selector);
      ListNode list = nodeFactory.list(null, memberExpression);
      ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
      result = nodeFactory.statementList(result, expressionStatement);
    }
    return result;
  }
  /*
   * Generate all necessary binding instance AST for any data bound overrides.
   */
  private StatementListNode genBindingInitializersAST(
      NodeFactory nodeFactory, StatementListNode statementList) {
    StatementListNode result = statementList;

    for (Iterator<StatesModel.Override> iter = bindingsQueue.iterator(); iter.hasNext(); ) {
      StatesModel.Override symbol = (StatesModel.Override) iter.next();

      QualifiedIdentifierNode qualifiedIdentifier =
          AbstractSyntaxTreeUtil.generateQualifiedIdentifier(
              nodeFactory, standardDefs.getBindingPackage(), BINDINGMANAGER, false);

      GetExpressionNode bindExpression = nodeFactory.getExpression(qualifiedIdentifier);

      MemberExpressionNode lvalue = nodeFactory.memberExpression(null, bindExpression);

      ArgumentListNode execArgs = nodeFactory.argumentList(null, nodeFactory.thisExpression(0));
      String decl = symbol.declaration.intern();
      execArgs = nodeFactory.argumentList(execArgs, nodeFactory.literalString(decl, false));
      IdentifierNode rvalIdentifier = nodeFactory.identifier(decl, false);
      GetExpressionNode getExpression = nodeFactory.getExpression(rvalIdentifier);
      MemberExpressionNode rvalue = nodeFactory.memberExpression(null, getExpression);
      execArgs = nodeFactory.argumentList(execArgs, rvalue);

      IdentifierNode bindIdentifier = nodeFactory.identifier(EXECUTEBINDINGS, false);

      CallExpressionNode selector =
          (CallExpressionNode) nodeFactory.callExpression(bindIdentifier, execArgs);
      selector.setRValue(false);

      MemberExpressionNode base = nodeFactory.memberExpression(lvalue, selector);
      ListNode list = nodeFactory.list(null, base);
      ExpressionStatementNode expressionStatement = nodeFactory.expressionStatement(list);
      result = nodeFactory.statementList(result, expressionStatement);
    }
    return result;
  }