/*
 * Copyright 2008 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.user.client.ui;

import com.google.gwt.animation.client.Animation;
import com.google.gwt.aria.client.Roles;
import com.google.gwt.core.client.GWT;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.i18n.client.LocaleInfo;
import com.google.gwt.safehtml.client.HasSafeHtml;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;

import java.util.ArrayList;
import java.util.List;

/**
 * An item that can be contained within a
 * {@link com.google.gwt.user.client.ui.Tree}.
 *
 * Each tree item is assigned a unique DOM id in order to support ARIA. See
 * {@link com.google.gwt.user.client.ui.Accessibility} for more information.
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.TreeExample}
 * </p>
 */
public class TreeItem extends UIObject implements IsTreeItem, HasTreeItems,
    HasHTML, HasSafeHtml {
  /*
   * For compatibility with UiBinder interface HasTreeItems should be declared
   * before HasHTML, so that children items and widgets are processed before
   * interpreting HTML.
   */

  /**
   * The margin applied to child items.
   */
  private static final double CHILD_MARGIN = 16.0;

  /**
   * Implementation class for {@link TreeItem}.
   */
  public static class TreeItemImpl {
    public TreeItemImpl() {
      initializeClonableElements();
    }

    void convertToFullNode(TreeItem item) {
      if (item.imageHolder == null) {
        // Extract the Elements from the object
        Element itemTable = DOM.clone(BASE_INTERNAL_ELEM, true);
        DOM.appendChild(item.getElement(), itemTable);
        Element tr = DOM.getFirstChild(DOM.getFirstChild(itemTable));
        Element tdImg = DOM.getFirstChild(tr);
        Element tdContent = DOM.getNextSibling(tdImg);

        // Undoes padding from table element.
        item.getElement().getStyle().setProperty("padding", "0px");
        DOM.appendChild(tdContent, item.contentElem);
        item.imageHolder = tdImg;
      }
    }

    /**
     * Setup clonable elements.
     */
    void initializeClonableElements() {
      if (GWT.isClient()) {
        // Create the base table element that will be cloned.
        BASE_INTERNAL_ELEM = DOM.createTable();
        Element contentElem = DOM.createDiv();
        Element tbody = DOM.createTBody(), tr = DOM.createTR();
        Element tdImg = DOM.createTD(), tdContent = DOM.createTD();
        DOM.appendChild(BASE_INTERNAL_ELEM, tbody);
        DOM.appendChild(tbody, tr);
        DOM.appendChild(tr, tdImg);
        DOM.appendChild(tr, tdContent);
        tdImg.getStyle().setProperty("verticalAlign", "middle");
        tdContent.getStyle().setProperty("verticalAlign", "middle");
        DOM.appendChild(tdContent, contentElem);
        contentElem.getStyle().setProperty("display", "inline");
        setStyleName(contentElem, "gwt-TreeItem");
        BASE_INTERNAL_ELEM.getStyle().setProperty("whiteSpace", "nowrap");

        // Create the base element that will be cloned
        BASE_BARE_ELEM = DOM.createDiv();

        // Simulates padding from table element.
        BASE_BARE_ELEM.getStyle().setProperty("padding", "3px");
        DOM.appendChild(BASE_BARE_ELEM, contentElem);
        Roles.getTreeitemRole().set(contentElem);
      }
    }
  }

  /**
   * IE specific implementation class for {@link TreeItem}.
   */
  public static class TreeItemImplIE8ToIE10 extends TreeItemImpl {
    @Override
    void convertToFullNode(TreeItem item) {
      super.convertToFullNode(item);
      item.getElement().getStyle().setProperty("marginBottom", "0px");
    }
  }

  /**
   * An {@link Animation} used to open the child elements. If a {@link TreeItem}
   * is in the process of opening, it will immediately be opened and the new
   * {@link TreeItem} will use this animation.
   */
  private static class TreeItemAnimation extends Animation {

    /**
     * The {@link TreeItem} currently being affected.
     */
    private TreeItem curItem = null;

    /**
     * Whether the item is being opened or closed.
     */
    private boolean opening = true;

    /**
     * The target height of the child items.
     */
    private int scrollHeight = 0;

    /**
     * Open the specified {@link TreeItem}.
     *
     * @param item the {@link TreeItem} to open
     * @param animate true to animate, false to open instantly
     */
    public void setItemState(TreeItem item, boolean animate) {
      // Immediately complete previous open
      cancel();

      // Open the new item
      if (animate) {
        curItem = item;
        opening = item.open;
        run(Math.min(ANIMATION_DURATION, ANIMATION_DURATION_PER_ITEM
            * curItem.getChildCount()));
      } else {
        UIObject.setVisible(item.childSpanElem, item.open);
      }
    }

    @Override
    protected void onComplete() {
      if (curItem != null) {
        if (opening) {
          UIObject.setVisible(curItem.childSpanElem, true);
          onUpdate(1.0);
          curItem.childSpanElem.getStyle().setProperty("height", "auto");
        } else {
          UIObject.setVisible(curItem.childSpanElem, false);
        }
        curItem.childSpanElem.getStyle().setProperty("overflow", "visible");
        curItem.childSpanElem.getStyle().setProperty("width", "auto");
        curItem = null;
      }
    }

    @Override
    protected void onStart() {
      scrollHeight = 0;

      // If the TreeItem is already open, we can get its scrollHeight
      // immediately.
      if (!opening) {
        scrollHeight = curItem.childSpanElem.getScrollHeight();
      }
      curItem.childSpanElem.getStyle().setProperty("overflow", "hidden");

      // If the TreeItem is already open, onStart will set its height to its
      // natural height. If the TreeItem is currently closed, onStart will set
      // its height to 1px (see onUpdate below), and then we make the TreeItem
      // visible so we can get its correct scrollHeight.
      super.onStart();

      // If the TreeItem is currently closed, we need to make it visible before
      // we can get its height.
      if (opening) {
        UIObject.setVisible(curItem.childSpanElem, true);
        scrollHeight = curItem.childSpanElem.getScrollHeight();
      }
    }

    @Override
    protected void onUpdate(double progress) {
      int height = (int) (progress * scrollHeight);
      if (!opening) {
        height = scrollHeight - height;
      }

      // Issue 2338: If the height is 0px, IE7 will display all of the children
      // instead of hiding them completely.
      height = Math.max(height, 1);

      curItem.childSpanElem.getStyle().setProperty("height", height + "px");

      // We need to set the width explicitly of the item might be cropped
      int scrollWidth = curItem.childSpanElem.getPropertyInt("scrollWidth");
      curItem.childSpanElem.getStyle().setProperty("width", scrollWidth + "px");
    }
  }

  // By not overwriting the default tree padding and spacing, we traditionally
  // added 7 pixels between our image and content.
  // <2>|<1>image<1>|<2>|<1>content
  // So to preserve the current spacing we must add a 7 pixel pad when no image
  // is supplied.
  static final int IMAGE_PAD = 7;

  /**
   * The duration of the animation.
   */
  private static final int ANIMATION_DURATION = 200;

  /**
   * The duration of the animation per child {@link TreeItem}. If the per item
   * duration times the number of child items is less than the duration above,
   * the smaller duration will be used.
   */
  private static final int ANIMATION_DURATION_PER_ITEM = 75;

  /**
   * The static animation used to open {@link TreeItem TreeItems}.
   */
  private static TreeItemAnimation itemAnimation = new TreeItemAnimation();

  /**
   * The structured table to hold images.
   */

  private static Element BASE_INTERNAL_ELEM;
  /**
   * The base tree item element that will be cloned.
   */
  private static Element BASE_BARE_ELEM;

  private static TreeItemImpl impl = GWT.create(TreeItemImpl.class);

  private ArrayList<TreeItem> children;
  private Element contentElem, childSpanElem, imageHolder;

  /**
   * Indicates that this item is a root item in a tree.
   */
  private boolean isRoot;

  private boolean open;
  private TreeItem parent;
  private boolean selected;

  private Object userObject;

  private Tree tree;

  private Widget widget;

  /**
   * Creates an empty tree item.
   */
  public TreeItem() {
    this(false);
  }

  /**
   * Constructs a tree item with the given HTML.
   *
   * @param html the item's HTML
   */
  public TreeItem(SafeHtml html) {
    this();
    setHTML(html);
  }

  /**
   * Constructs a tree item with the given <code>Widget</code>.
   *
   * @param widget the item's widget
   */
  public TreeItem(Widget widget) {
    this();
    setWidget(widget);
  }

  /**
   * Creates an empty tree item.
   *
   * @param isRoot true if this item is the root of a tree
   */
  TreeItem(boolean isRoot) {
    this.isRoot = isRoot;
    Element elem = DOM.clone(BASE_BARE_ELEM, true);
    setElement(elem);
    contentElem = DOM.getFirstChild(elem);
    contentElem.setAttribute("id", DOM.createUniqueId());

    // The root item always has children.
    if (isRoot) {
      initChildren();
    }
  }

  /**
   * Adds a child tree item containing the specified html.
   *
   * @param itemHtml the item's HTML
   * @return the item that was added
   */
  @Override
  public TreeItem addItem(SafeHtml itemHtml) {
    TreeItem ret = new TreeItem(itemHtml);
    addItem(ret);
    return ret;
  }

  /**
   * Adds another item as a child to this one.
   *
   * @param item the item to be added
   */
  @Override
  public void addItem(TreeItem item) {
    // If this is the item's parent, removing the item will affect the child
    // count.
    maybeRemoveItemFromParent(item);
    insertItem(getChildCount(), item);
  }

  /**
   * Adds another item as a child to this one.
   *
   * @param isItem the wrapper of item to be added
   */
  @Override
  public void addItem(IsTreeItem isItem) {
    TreeItem item = isItem.asTreeItem();
    addItem(item);
  }

  /**
   * Adds a child tree item containing the specified widget.
   *
   * @param widget the widget to be added
   * @return the item that was added
   */
  @Override
  public TreeItem addItem(Widget widget) {
    TreeItem ret = new TreeItem(widget);
    addItem(ret);
    return ret;
  }

  /**
   * Adds a child tree item containing the specified text.
   *
   * @param itemText the text of the item to be added
   * @return the item that was added
   */
  @Override
  public TreeItem addTextItem(String itemText) {
    TreeItem ret = new TreeItem();
    ret.setText(itemText);
    addItem(ret);
    return ret;
  }

  @Override
  public TreeItem asTreeItem() {
    return this;
  }

  /**
   * Gets the child at the specified index.
   *
   * @param index the index to be retrieved
   * @return the item at that index
   */

  public TreeItem getChild(int index) {
    if ((index < 0) || (index >= getChildCount())) {
      return null;
    }

    return children.get(index);
  }

  /**
   * Gets the number of children contained in this item.
   *
   * @return this item's child count.
   */

  public int getChildCount() {
    if (children == null) {
      return 0;
    }
    return children.size();
  }

  /**
   * Gets the index of the specified child item.
   *
   * @param child the child item to be found
   * @return the child's index, or <code>-1</code> if none is found
   */

  public int getChildIndex(TreeItem child) {
    if (children == null) {
      return -1;
    }
    return children.indexOf(child);
  }

  @Override
  public String getHTML() {
    return contentElem.getInnerHTML();
  }

  /**
   * Gets this item's parent.
   *
   * @return the parent item
   */
  public TreeItem getParentItem() {
    return parent;
  }

  /**
   * Gets whether this item's children are displayed.
   *
   * @return <code>true</code> if the item is open
   */
  public boolean getState() {
    return open;
  }

  @Override
  public String getText() {
    return contentElem.getInnerText();
  }

  /**
   * Gets the tree that contains this item.
   *
   * @return the containing tree
   */
  public final Tree getTree() {
    return tree;
  }

  /**
   * Gets the user-defined object associated with this item.
   *
   * @return the item's user-defined object
   */
  public Object getUserObject() {
    return userObject;
  }

  /**
   * Gets the <code>Widget</code> associated with this tree item.
   *
   * @return the widget
   */
  public Widget getWidget() {
    return widget;
  }

  @Override
  public String getTitle() {
    return contentElem.getTitle();
  }

  @Override
  public void setTitle(String title) {
    contentElem.setTitle(title);
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * html.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param itemHtml the item's HTML
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertItem(int beforeIndex, SafeHtml itemHtml)
      throws IndexOutOfBoundsException {
    TreeItem ret = new TreeItem(itemHtml);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Inserts an item as a child to this one.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param item the item to be added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public void insertItem(int beforeIndex, TreeItem item)
      throws IndexOutOfBoundsException {
    // Detach item from existing parent.
    maybeRemoveItemFromParent(item);

    // Check the index after detaching in case this item was already the parent.
    int childCount = getChildCount();
    if (beforeIndex < 0 || beforeIndex > childCount) {
      throw new IndexOutOfBoundsException();
    }

    if (children == null) {
      initChildren();
    }

    // Set the margin.
    // Use no margin on top-most items.
    double margin = isRoot ? 0.0 : CHILD_MARGIN;
    if (LocaleInfo.getCurrentLocale().isRTL()) {
      item.getElement().getStyle().setMarginRight(margin, Unit.PX);
    } else {
      item.getElement().getStyle().setMarginLeft(margin, Unit.PX);
    }

    // Physical attach.
    Element childContainer = isRoot ? tree.getElement() : childSpanElem;
    if (beforeIndex == childCount) {
      childContainer.appendChild(item.getElement());
    } else {
      Element beforeElem = getChild(beforeIndex).getElement();
      childContainer.insertBefore(item.getElement(), beforeElem);
    }

    // Logical attach.
    // Explicitly set top-level items' parents to null if this is root.
    item.setParentItem(isRoot ? null : this);
    children.add(beforeIndex, item);

    // Adopt.
    item.setTree(tree);

    if (!isRoot && children.size() == 1) {
      updateState(false, false);
    }
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * widget.
   *
   * @param beforeIndex the index where the item will be inserted
   * @param widget the widget to be added
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertItem(int beforeIndex, Widget widget)
      throws IndexOutOfBoundsException {
    TreeItem ret = new TreeItem(widget);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Inserts a child tree item at the specified index containing the specified
   * text.
   * 
   * @param beforeIndex the index where the item will be inserted
   * @param itemText the item's text
   * @return the item that was added
   * @throws IndexOutOfBoundsException if the index is out of range
   */
  public TreeItem insertTextItem(int beforeIndex, String itemText) {
    TreeItem ret = new TreeItem();
    ret.setText(itemText);
    insertItem(beforeIndex, ret);
    return ret;
  }

  /**
   * Determines whether this item is currently selected.
   *
   * @return <code>true</code> if it is selected
   */
  public boolean isSelected() {
    return selected;
  }

  /**
   * Removes this item from its tree.
   */
  public void remove() {
    if (parent != null) {
      // If this item has a parent, remove self from it.
      parent.removeItem(this);
    } else if (tree != null) {
      // If the item has no parent, but is in the Tree, it must be a top-level
      // element.
      tree.removeItem(this);
    }
  }

  /**
   * Removes one of this item's children.
   *
   * @param item the item to be removed
   */
  @Override
  public void removeItem(TreeItem item) {
    // Validate.
    if (children == null || !children.contains(item)) {
      return;
    }

    // Orphan.
    Tree oldTree = tree;
    item.setTree(null);

    // Physical detach.
    if (isRoot) {
      oldTree.getElement().removeChild(item.getElement());
    } else {
      childSpanElem.removeChild(item.getElement());
    }

    // Logical detach.
    item.setParentItem(null);
    children.remove(item);

    if (!isRoot && children.size() == 0) {
      updateState(false, false);
    }
  }

  /**
   * Removes one of this item's children.
   *
   * @param isItem the wrapper of item to be removed
   */
  @Override
  public void removeItem(IsTreeItem isItem) {
    if (isItem != null) {
      TreeItem item = isItem.asTreeItem();
      removeItem(item);
    }
  }

  /**
   * Removes all of this item's children.
   */
  @Override
  public void removeItems() {
    while (getChildCount() > 0) {
      removeItem(getChild(0));
    }
  }

  @Override
  public void setHTML(String html) {
    setWidget(null);
    contentElem.setInnerHTML(html);
  }

  @Override
  public void setHTML(SafeHtml html) {
    setHTML(html.asString());
  }

  /**
   * Selects or deselects this item.
   *
   * @param selected <code>true</code> to select the item, <code>false</code> to
   *          deselect it
   */
  public void setSelected(boolean selected) {
    if (this.selected == selected) {
      return;
    }
    this.selected = selected;
    setStyleName(getContentElem(), "gwt-TreeItem-selected", selected);
  }

  /**
   * Sets whether this item's children are displayed.
   *
   * @param open whether the item is open
   */
  public void setState(boolean open) {
    setState(open, true);
  }

  /**
   * Sets whether this item's children are displayed.
   *
   * @param open whether the item is open
   * @param fireEvents <code>true</code> to allow open/close events to be
   */
  public void setState(boolean open, boolean fireEvents) {
    if (open && getChildCount() == 0) {
      return;
    }

    // Only do the physical update if it changes
    if (this.open != open) {
      this.open = open;
      updateState(true, true);

      if (fireEvents && tree != null) {
        tree.fireStateChanged(this, open);
      }
    }
  }

  @Override
  public void setText(String text) {
    setWidget(null);
    contentElem.setInnerText(text);
  }

  /**
   * Sets the user-defined object associated with this item.
   *
   * @param userObj the item's user-defined object
   */
  public void setUserObject(Object userObj) {
    userObject = userObj;
  }

  /**
   * Sets the current widget. Any existing child widget will be removed.
   *
   * @param newWidget Widget to set
   */
  public void setWidget(Widget newWidget) {
    // Detach new child from old parent.
    if (newWidget != null) {
      newWidget.removeFromParent();
    }

    // Detach old child from tree.
    if (widget != null) {
      try {
        if (tree != null) {
          tree.orphan(widget);
        }
      } finally {
        // Physical detach old child.
        contentElem.removeChild(widget.getElement());
        widget = null;
      }
    }

    // Clear out any existing content before adding a widget.
    contentElem.setInnerHTML("");

    // Logical detach old/attach new.
    widget = newWidget;

    if (newWidget != null) {
      // Physical attach new.
      DOM.appendChild(contentElem, newWidget.getElement());

      // Attach child to tree.
      if (tree != null) {
        tree.adopt(widget, this);
      }

      // Set tabIndex on the widget to -1, so that it doesn't mess up the tab
      // order of the entire tree

      if (Tree.shouldTreeDelegateFocusToElement(widget.getElement())) {
        widget.getElement().setAttribute("tabIndex", "-1");
      }
    }
  }

  /**
   * Returns a suggested {@link Focusable} instance to use when this tree item
   * is selected. The tree maintains focus if this method returns null. By
   * default, if the tree item contains a focusable widget, that widget is
   * returned.
   *
   * Note, the {@link Tree} will ignore this value if the user clicked on an
   * input element such as a button or text area when selecting this item.
   *
   * @return the focusable item
   */
  protected Focusable getFocusable() {
    Focusable focus = getFocusableWidget();
    if (focus == null) {
      Widget w = getWidget();
      if (w instanceof Focusable) {
        focus = (Focusable) w;
      }
    }
    return focus;
  }

  /**
   * Returns the widget, if any, that should be focused on if this TreeItem is
   * selected.
   *
   * @return widget to be focused.
   * @deprecated use {@link #getFocusable()} instead
   */
  @Deprecated
  protected HasFocus getFocusableWidget() {
    Widget w = getWidget();
    if (w instanceof HasFocus) {
      return (HasFocus) w;
    } else {
      return null;
    }
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-content = The text or {@link Widget} next to the image.</li>
   * <li>-child# = The child at the specified index.</li>
   * </ul>
   *
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    super.onEnsureDebugId(baseID);
    ensureDebugId(contentElem, baseID, "content");
    if (imageHolder != null) {
      // The image itself may or may not exist.
      ensureDebugId(imageHolder, baseID, "image");
    }

    if (children != null) {
      int childCount = 0;
      for (TreeItem child : children) {
        child.ensureDebugId(baseID + "-child" + childCount);
        childCount++;
      }
    }
  }

  void addTreeItems(List<TreeItem> accum) {
    int size = getChildCount();
    for (int i = 0; i < size; i++) {
      TreeItem item = children.get(i);
      accum.add(item);
      item.addTreeItems(accum);
    }
  }

  ArrayList<TreeItem> getChildren() {
    return children;
  }

  Element getContentElem() {
    return contentElem;
  }

  Element getImageElement() {
    return DOM.getFirstChild(getImageHolderElement());
  }

  Element getImageHolderElement() {
    if (!isFullNode()) {
      convertToFullNode();
    }
    return imageHolder;
  }

  void initChildren() {
    convertToFullNode();
    childSpanElem = DOM.createDiv();
    DOM.appendChild(getElement(), childSpanElem);
    childSpanElem.getStyle().setProperty("whiteSpace", "nowrap");
    children = new ArrayList<TreeItem>();
  }

  boolean isFullNode() {
    return imageHolder != null;
  }

  /**
   * Remove a tree item from its parent if it has one.
   *
   * @param item the tree item to remove from its parent
   */
  void maybeRemoveItemFromParent(TreeItem item) {
    if ((item.getParentItem() != null) || (item.getTree() != null)) {
      item.remove();
    }
  }

  void setParentItem(TreeItem parent) {
    this.parent = parent;
  }

  void setTree(Tree newTree) {
    // Early out.
    if (tree == newTree) {
      return;
    }

    // Remove this item from existing tree.
    if (tree != null) {
      if (tree.getSelectedItem() == this) {
        tree.setSelectedItem(null);
      }

      if (widget != null) {
        tree.orphan(widget);
      }
    }

    tree = newTree;
    for (int i = 0, n = getChildCount(); i < n; ++i) {
      children.get(i).setTree(newTree);
    }
    updateState(false, true);

    if (newTree != null) {
      if (widget != null) {
        // Add my widget to the new tree.
        newTree.adopt(widget, this);
      }
    }
  }

  void updateState(boolean animate, boolean updateTreeSelection) {
    // If the tree hasn't been set, there is no visual state to update.
    // If the tree is not attached, then update will be called on attach.
    if (tree == null || tree.isAttached() == false) {
      return;
    }

    if (getChildCount() == 0) {
      if (childSpanElem != null) {
        UIObject.setVisible(childSpanElem, false);
      }
      tree.showLeafImage(this);
      return;
    }

    // We must use 'display' rather than 'visibility' here,
    // or the children will always take up space.
    if (animate && (tree != null) && (tree.isAttached())) {
      itemAnimation.setItemState(this, tree.isAnimationEnabled());
    } else {
      itemAnimation.setItemState(this, false);
    }

    // Change the status image
    if (open) {
      tree.showOpenImage(this);
    } else {
      tree.showClosedImage(this);
    }

    // We may need to update the tree's selection in response to a tree state
    // change. For example, if the tree's currently selected item is a
    // descendant of an item whose branch was just collapsed, then the item
    // itself should become the newly-selected item.
    if (updateTreeSelection) {
      tree.maybeUpdateSelection(this, this.open);
    }
  }

  void updateStateRecursive() {
    updateStateRecursiveHelper();
    tree.maybeUpdateSelection(this, this.open);
  }

  private void convertToFullNode() {
    impl.convertToFullNode(this);
  }

  private void updateStateRecursiveHelper() {
    updateState(false, false);
    for (int i = 0, n = getChildCount(); i < n; ++i) {
      children.get(i).updateStateRecursiveHelper();
    }
  }
}
