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

package com.google.dart.compiler.ast;

import com.google.dart.compiler.common.AbstractNode;
import com.google.dart.compiler.resolver.Element;
import com.google.dart.compiler.type.Type;
import com.google.dart.compiler.util.DefaultTextOutput;

import java.util.List;

/**
 * Base class for all Dart AST nodes.
 */
public abstract class DartNode extends AbstractNode {
  private DartNode parent;
  private Type type;

  public final String toSource() {
    DefaultTextOutput out = new DefaultTextOutput(false);
    accept(new DartToSourceVisitor(out));
    return out.toString();
  }

  public Element getElement() {
    return null;
  }

  public void setElement(Element element) {
    throw new UnsupportedOperationException(getClass().getSimpleName());
  }

  public void setType(Type type) {
    this.type = type;
  }

  public Type getType() {
    return type;
  }

  @Override
  public String toString() {
    return this.toSource();
  }

  /**
   * Returns this node's parent node, or <code>null</code> if this is the
   * root node.
   * <p>
   * Note that the relationship between an AST node and its parent node
   * may change over the lifetime of a node.
   *
   * @return the parent of this node, or <code>null</code> if none
   */
  public final DartNode getParent() {
    return parent;
  }

  /**
   * Return the node at the root of this node's AST structure. Note that this
   * method's performance is linear with respect to the depth of the node in
   * the AST structure (O(depth)).
   *
   * @return the node at the root of this node's AST structure
   */
  public final DartNode getRoot() {
    DartNode root = this;
    DartNode parent = getParent();
    while (parent != null) {
      root = parent;
      parent = root.getParent();
    }
    return root;
  }

  protected <T extends DartNode> T becomeParentOf(T child) {
    if (child != null) {
      DartNode node = child; // Java 7 access rules require a temp of a concrete type.
      node.setParent(this);
    }
    return child;
  }

  protected <L extends List<? extends DartNode>> L becomeParentOf(L children) {
    if (children != null) {
      for (DartNode child : children) {
        child.setParent(this);
      }
    }
    return children;
  }

  private void setParent(DartNode newParent) {
    parent = newParent;
  }

  public abstract void visitChildren(ASTVisitor<?> visitor);

  public abstract <R> R accept(ASTVisitor<R> visitor);

  @Override
  public DartNode clone() {
    // TODO (fabiomfv) - Implement proper cloning when strictly needed.
    return this;
  }

  public String getObjectIdentifier(){
    return super.toString();
  }

  /**
   * If the given child is not <code>null</code>, use the given visitor to visit it.
   * 
   * @param child the child to be visited
   * @param visitor the visitor that will be used to visit the child
   */
  protected void safelyVisitChild(DartNode child, ASTVisitor<?> visitor) {
    if (child != null) {
      child.accept(visitor);
    }
  }
  
}
