/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.myfaces.trinidadinternal.renderkit.core.xhtml;

import java.io.IOException;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;

import org.apache.myfaces.trinidad.bean.FacesBean;
import org.apache.myfaces.trinidad.bean.PropertyKey;
import org.apache.myfaces.trinidad.component.UIXHierarchy;
import org.apache.myfaces.trinidad.component.UIXTree;
import org.apache.myfaces.trinidad.component.core.data.CoreTree;
import org.apache.myfaces.trinidad.context.Agent;
import org.apache.myfaces.trinidad.context.FormData;
import org.apache.myfaces.trinidad.context.RenderingContext;
import org.apache.myfaces.trinidad.context.RequestContext;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.model.RowKeySet;
import org.apache.myfaces.trinidad.skin.Icon;
import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.table.TreeUtils;


/**
 * Renderer for trees.
 *
 */
public class TreeRenderer extends XhtmlRenderer
{
  public TreeRenderer()
  {
    this(CoreTree.TYPE);
  }

  protected TreeRenderer(
    FacesBean.Type type)
  {
    super(type);
  }

  @Override
  protected void findTypeConstants(
    FacesBean.Type type)
  {
    super.findTypeConstants(type);
    _immediateKey = type.findKey("immediate");
  }

  @Override
  public boolean getRendersChildren()
  {
    return true;
  }

  /**
   * @todo do not mess with selection here. queue an event.
   */
  @SuppressWarnings("unchecked")
  @Override
  protected void decode(
    FacesContext facesContext,
    UIComponent  component,
    @SuppressWarnings("unused")
    FacesBean    facesBean,
    String       clientId)
  {
    Map<String, String> parameters =
      facesContext.getExternalContext().getRequestParameterMap();
    String source = parameters.get(XhtmlConstants.SOURCE_PARAM);

    if (clientId == null)
    {
      clientId = getClientId(facesContext, component);
    }
    if (!clientId.equals(source))
      return;

    TreeUtils.decodeExpandEvents(parameters, component,
                                 Collections.emptyList());
    String currencyStrParam =
      source + NamingContainer.SEPARATOR_CHAR + SELECTED_PARAM;
    String currencyStr = parameters.get(currencyStrParam);
    if ((currencyStr != null) && (!"".equals(currencyStr)))
    {
      UIXTree tree = (UIXTree) component;
      Object oldPath = tree.getRowKey();
      tree.setClientRowKey(currencyStr);
      tree.getSelectedRowKeys().clear();
      tree.getSelectedRowKeys().add();
      tree.setRowKey(oldPath);
    }

    RequestContext.getCurrentInstance().addPartialTarget(component);
  }

  @Override
  protected void encodeAll(
    FacesContext     context,
    RenderingContext rc,
    UIComponent      component,
    FacesBean        bean
    ) throws IOException
  {
    // Since Train is a naming container, we can be more
    // efficient about skipping its children
    if (!PartialPageUtils.containsPprTargets(rc,
                                             component,
                                             getClientId(context, component)))
    {
      return;
    }

    UIXHierarchy tree = (UIXHierarchy) component;
    TreeUtils.expandFocusRowKey((UIXTree) component);

    Object oldPath = tree.getRowKey();
    try
    {
      boolean continueRendering = setInitialPath(tree, bean);
      if (!continueRendering)
        return;

      _renderContent(context, rc, tree, bean);
    }
    finally
    {
      tree.setRowKey(oldPath);
    }
  }

  @Override
  protected boolean shouldRenderId(
    FacesContext context,
    UIComponent  component)
  {
    return true;
  }

  private void _renderContent(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    FacesBean        bean
    ) throws IOException
  {
    FormData fd = rc.getFormData();
    if (fd == null)
    {
      _LOG.warning("TREE_COMPONENT_MUST_INSIDE_FORM");
      return;
    }

    ResponseWriter rw = context.getResponseWriter();
    rw.startElement("div", tree);
    renderId(context, tree);
    renderAllAttributes(context, rc, tree, bean);

    final String id = getClientId(context, tree);
    UIComponent stamp = getFacet(tree, CoreTree.NODE_STAMP_FACET);

    //@todo - will this tree.getFocusPath survive?
    //    List focusPath = getFocusPath(context, node);
    Object focusPath = tree.getFocusRowKey();
    String formName = fd.getName();

    // Bug 3931544:  don't use colons in Javascript variable names.
    // We'll just replace colons with underscores;  not perfect, but adequate
    final String varName = "_adftree" + XhtmlUtils.getJSIdentifier(id);

    boolean leftToRight = !rc.isRightToLeft();
    int rootSize = tree.getRowCount();
    RowKeySet state = getExpandedRowKeys(tree);
    Map<Object, Boolean> selectedPaths = getSelectedPaths(focusPath);

    // render each of the root nodes
    for (int i = 0; i < rootSize; i++)
    {
      tree.setRowIndex(i);
      _renderNode(context, rc, tree, bean, stamp, varName, state,
                  selectedPaths, new Boolean[_DEFAULT_TREE_DEPTH],
                  leftToRight, (i == 0), (i == rootSize - 1), 0);
    }

    //HKuhn - not needed in printable mode (scripting disabled)
    if (supportsScripting(rc))
    {
      rw.startElement("script", null);
      renderScriptDeferAttribute(context, rc);
      renderScriptTypeAttribute(context, rc);

      _renderTreeJS(context, rc, tree, bean);

      //out.writeText("_setNodes('"+name+"','"+nodesRendered+"');");

      String selectedParam =
        id + NamingContainer.SEPARATOR_CHAR + SELECTED_PARAM;
      String focusNodeId = TreeUtils.getFocusNodeClientId(context, tree);

      rw.writeText("var " + varName + " = " +
                       _createNewJSSelectionState(formName, id, selectedParam,
                                                  focusNodeId), null);
      rw.endElement("script");

      fd.addNeededValue(selectedParam);
    }
    rw.endElement("div");

    fd.addNeededValue(_PATH_PARAM);

  }

  // return whether to continue with rendering

  protected boolean setInitialPath(
    UIXHierarchy tree,
    FacesBean    bean)
  {
    tree.setRowKey(null);
    return true;
  }

  private boolean _isShownSelected(
    UIXHierarchy         tree,
    Map<Object, Boolean> selectedPaths,
    Object               currPath)
  {

    boolean selected = false;
    if (tree instanceof UIXTree)
      selected = ((UIXTree) tree).getSelectedRowKeys().isContained();

    if (selected)
      return true;

    Object value = selectedPaths.get(currPath);

    if (value != null)
      return true;

    return false;
  }

  protected Map<Object, Boolean> getSelectedPaths(
    Object focusPath)
  {
    if (focusPath == null)
      return new HashMap<Object, Boolean>(0);

    Map<Object, Boolean> selectedPaths = new HashMap<Object, Boolean>(1);

    selectedPaths.put(focusPath, Boolean.TRUE);
    return selectedPaths;
  }

  protected RowKeySet getExpandedRowKeys(
    UIXHierarchy tree)
  {
    return ((UIXTree) tree).getDisclosedRowKeys();
  }

  /**
   * Returns true if the tree connecting lines should be rendered
   * @param rc the RenderingContext
   * @return the value of the AF_TREE_SHOW_LINES skin property
   */
  protected boolean isShowLines(
    RenderingContext rc)
  {
    Object showLines = rc.getSkin().getProperty(SkinProperties.AF_TREE_SHOW_LINES);
    return showLines == null || showLines.equals(Boolean.TRUE);
  }

  /**
   * Returns the URI of the vertical line icon
   *
   * @param context     the FacesContext
   * @param rc          the RenderingContext
   * @param isLine      if there is need for a vertical line
   * @param leftToRight left to right
   * @return the URI of the icon
   */
  protected String getConnectingBackgroundIcon(
    FacesContext     context,
    RenderingContext rc,
    boolean          isLine,
    boolean          leftToRight)
  {
    if (!isLine || !isShowLines(rc))
      return null;
    Icon icon = rc.getIcon(SkinSelectors.AF_TREE_LINE_ICON);
    return (icon == null) ? null : icon.getImageURI(context, rc).toString();
  }

  /**
   * Returns the URI of the expanded-icon's background icon
   * Usually the lines connecting a node
   * @param context the FacesContext
   * @param rc the RenderingContext
   * @param isLastSibling true if the node is the last child of its parent node
   * @param isLeftToRight left to right
   * @return the URI of the icon
   */
  protected String getIconBackgroundIcon(
    FacesContext     context,
    RenderingContext rc,
    boolean          isLastSibling,
    boolean          isLeftToRight)
  {
    Object showLines = rc.getSkin().getProperty(SkinProperties.AF_TREE_SHOW_LINES);
    if (!isShowLines(rc))
      return null;
    Icon nodeBackgroundIcon = rc.getIcon(isLastSibling
        ? SkinSelectors.AF_TREE_LINE_LAST_ICON : SkinSelectors.AF_TREE_LINE_MIDDLE_ICON);
    return (nodeBackgroundIcon != null)
        ? nodeBackgroundIcon.getImageURI(context, rc).toString() : null;
  }

  // render the correct icon for a specific node

  protected void renderExpandCell(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    int              expanded,
    boolean          isLastSibling,
    String           onclick
    ) throws IOException
  {
    Icon icon = null;
    String iconURI = null;

    String backgroundIconURI;
    String nodeBackgroundIconURI;

    boolean isAbsoluteImageURI = true;

    String iconHeight = null;

    Object altText = null;

    String text = null;

    boolean isMacOS =
               Agent.PLATFORM_MACOS.equals(rc.getAgent().getPlatformName());
    // add in the expandability
    switch (expanded)
    {
      case NO_CHILDREN:
        icon = rc.getIcon(SkinSelectors.AF_TREE_NO_CHILDREN_ICON);
        if (icon == null || icon.getImageURI(context, rc) == null)
        {
          iconURI = TRANSPARENT_GIF;
          iconHeight = _ICON_HEIGHT;
          isAbsoluteImageURI = false;
        }
        break;
      case EXPAND_CLOSED:
        // "\u21D2"; // Double Arrow right

        if (isMacOS)
          // single arrow left
          text = rc.isRightToLeft() ? "\u2190" : "\u2192"; // single arrow right
        else if (isPDA(rc))
          //for PDAs use a simple "+" or "-" since miscellaneous unicode characters
          //are not supported
          text = "[+]"; //plus sign
        else // triangle left
          text = rc.isRightToLeft() ? "\u25C4" : "\u25BA"; // triangle right

        altText = rc.getTranslatedString(_EXPAND_TIP_KEY);
        icon = rc.getIcon(SkinSelectors.AF_TREE_COLLAPSED_ICON);
        break;
      case EXPAND_OPEN:
        //"\u21D3"; // double arrow down
        if (isMacOS)
          text = "\u2193"; // single arrow down
        else if (isPDA(rc))
          //for PDAs use a simple "+" or "-" since miscellaneous unicode characters
          //are not supported
          text = "[-]"; //plus sign
        else
          text = "\u25BC"; // triangle down

        altText = rc.getTranslatedString(_COLLAPSE_TIP_KEY);
        icon = rc.getIcon(SkinSelectors.AF_TREE_EXPANDED_ICON);
        break;
      case EXPAND_ALWAYS:
        if (isMacOS)
          text = "\u2193"; // single arrow down
        else if (isPDA(rc))
          text = "[-]"; //plus sign
        else
          text = "\u25BC"; // triangle down
        //for PDAs use a simple "+" or "-" since miscellaneous unicode character
        //s are not supported

        altText = rc.getTranslatedString(_DISABLED_COLLAPSE_TIP_KEY);
        icon = rc.getIcon(SkinSelectors.AF_TREE_EXPANDED_ICON);
        break;
    }

    if (iconURI == null && icon != null)
    {
      //This can be null so we need to check for it before doing toString
      Object o = icon.getImageURI(context, rc);
      if(o != null)
      {
        iconURI = o.toString();
      }
    }

    backgroundIconURI = getConnectingBackgroundIcon(context, rc, !isLastSibling, true);
    nodeBackgroundIconURI = getIconBackgroundIcon(context, rc, isLastSibling, true);

    if (iconURI != null)
    {
      renderExpandIconCell(context, rc,
                            backgroundIconURI, nodeBackgroundIconURI,
                            iconURI, isAbsoluteImageURI,
                            altText, _ICON_WIDTH, iconHeight, onclick);
    } else
    {
      _renderTextCell(context, rc, tree, expanded, text, altText, _ICON_WIDTH, onclick,
                      SkinSelectors.TREE_DISCLOSED_SYMBOL_STYLE_CLASS);
    }
  }

  private void _renderTextCell(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    int              expanded,
    String           text,
    Object           altText,
    String           width,
    String           onclick,
    String           styleClass
    ) throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
    writer.writeAttribute(XhtmlConstants.WIDTH_ATTRIBUTE, width, null);
    writer.writeAttribute("title", altText, null);
    renderStyleClass(context, rc, styleClass);
    boolean jsSupport = supportsScripting(rc);

    if (onclick != null)
    {
      if (jsSupport)
      {
        writer.startElement(XhtmlConstants.LINK_ELEMENT, null);
        writer.writeAttribute(XhtmlConstants.HREF_ATTRIBUTE, "#", null);
        writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, onclick, null);
      }
      else
      {
        // For Non-JavaScript browsers, render an input element(type= submit) to
        // submit the page. Encode the name attribute with the parameter name
        // and value thus it would enable the browsers to include the name of
        // this element in its payLoad if it submits the page.
        String nameAttr = TreeUtils.renderEncodedNameAttri(
                                        context,
                                        rc,
                                        tree,
                                        getClientId(context, tree),
                                        expanded == EXPAND_CLOSED);

        writer.startElement("input", null);
        writer.writeAttribute("type", "submit",null);
        writer.writeAttribute("name", nameAttr, null);
        writer.writeAttribute("value", text, null);
      }
    }

    if (text != null && jsSupport)
      writer.writeText(text, null);

    if (onclick != null)
    {
      if (jsSupport)
      {
        writer.endElement(XhtmlConstants.LINK_ELEMENT);
      }
      else
      {
        writer.endElement("input");
      }
    }

    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
  }

  protected void renderExpandIconCell(
    FacesContext     context,
    RenderingContext rc,
    String           backgroundIcon,
    String           nodeBackgroundIcon,
    String           icon,
    boolean          isIconAbsoluteURI,
    Object           altText,
    String           width,
    String           height,
    String           onclick
    ) throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
    writer.writeAttribute(XhtmlConstants.WIDTH_ATTRIBUTE, width, null);
    writer.writeAttribute(XhtmlConstants.HEIGHT_ATTRIBUTE, "100%", null);
    writer.writeAttribute(XhtmlConstants.VALIGN_ATTRIBUTE, XhtmlConstants.V_ALIGN_TOP,
                          null);

    if (backgroundIcon != null)
    {
//      String backgroundIconURI = getAbsoluteImageUri(context, rc, backgroundIcon);
      writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE,
                            _BACKGROUND_IMAGE_URL + backgroundIcon +
                                _END_FUNC, null);
    }

    if (nodeBackgroundIcon != null)
    {
      writer.startElement(XhtmlConstants.DIV_ELEMENT, null);
      writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE,
                            _BACKGROUND_IMAGE_URL + nodeBackgroundIcon +
                                _END_FUNC + _BACKGROUND_NO_REPEAT, null);
    }

    if (onclick != null)
    {
      writer.startElement(XhtmlConstants.LINK_ELEMENT, null);
      writer.writeAttribute(XhtmlConstants.HREF_ATTRIBUTE, "#", null);
      writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, onclick, null);
    }

    _renderIcon(context, rc, icon, isIconAbsoluteURI, altText, null, height);

    if (onclick != null)
    {
      writer.endElement(XhtmlConstants.LINK_ELEMENT);
    }

    if (nodeBackgroundIcon != null)
    {
      writer.endElement(XhtmlConstants.DIV_ELEMENT);
    }

    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
  }


  protected void renderIconCell(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    String           backgroundIcon,
    String           icon,
    boolean          isIconAbsoluteURI,
    Object           altText,
    String           width,
    String           height,
    String           onclick
    ) throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
    writer.writeAttribute(XhtmlConstants.WIDTH_ATTRIBUTE, width, null);

    if (backgroundIcon != null)
    {
      String backgroundIconURI = backgroundIcon;//getAbsoluteImageUri(context, rc, backgroundIcon);
      writer.writeAttribute(XhtmlConstants.STYLE_ATTRIBUTE,
                            _BACKGROUND_IMAGE_URL + backgroundIconURI +
                            _END_FUNC, null);
    }

    if (onclick != null)
    {
      writer.startElement(XhtmlConstants.LINK_ELEMENT, null);
      writer.writeAttribute(XhtmlConstants.HREF_ATTRIBUTE, "#", null);
      writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, onclick, null);
      String treeName = getClientId(context, tree);
      String id = treeName + NamingContainer.SEPARATOR_CHAR + "lnk";
      writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE, id, null);
    }

    _renderIcon(context, rc, icon, isIconAbsoluteURI, altText, width, height);

    if (onclick != null)
    {
      writer.endElement(XhtmlConstants.LINK_ELEMENT);
    }

    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
  }


  private static String _createFocusNodeGetter(
    String focusNodeId)
  {
    return (focusNodeId != null) ? "document.getElementById('" + focusNodeId + "')" : null;
  }

  private static String _callJSSelect(
    UIXHierarchy tree,
    String       jsVarName)
  {
    String currencyStr = tree.getClientRowKey();
    return jsVarName + ".select(this,'" + currencyStr + "');";
  }

  private String _createNewJSSelectionState(
    String formName,
    String treeClientId,
    String selectParam,
    String focusNodeId)
  {
    String treeState = TreeUtils.createNewJSCollectionComponentState(formName, treeClientId);
    String focusNode = _createFocusNodeGetter(focusNodeId);
    String jsSelectionState = null;
    if (focusNode == null)
    {
      jsSelectionState = "new _adfTreeSelector('" + selectParam + "'," + treeState + ");";
    }
    else
    {
      jsSelectionState = "new _adfTreeSelector('" + selectParam + "'," + treeState + "," + focusNode + ");";
    }
    return jsSelectionState;
  }

  private void _renderTreeJS(
    FacesContext     context,
    RenderingContext rc,
    UIComponent      component,
    FacesBean        bean
    ) throws IOException
  {
    if (!rc.getProperties().containsKey(_JS_RENDERED_KEY))
    {
      rc.getProperties().put(_JS_RENDERED_KEY, Boolean.TRUE);
      ResponseWriter writer = context.getResponseWriter();
      writer.writeText("function _adfTreeSelector(selectParam,tState,focusNode) {" +
                       "this._selectParam = selectParam;" +
                       "this.treeState = tState;" +
                       "this._pTag = focusNode;" +
                       "}" +
                       "_adfTreeSelector.prototype.select = function(tag,path) {" +
                       "if (this._pTag != null) {" +
                       "this._pTag.className='" + SkinSelectors.TREE_ROW_STYLE_CLASS +
                       "';" + "}" + "this._pTag = tag;" +
                       //if there are any problems see TRINIDAD-935
                       "tag.className='" + SkinSelectors.TREE_ROW_SELECTED_STYLE_CLASS +
                       "';" + "};", null);


      // _setSelection(..) and _getSelection(..) are called by the
      // ClientStateTreeDataProxy (if selection is enabled for this particular
      // tree). _setSelection is called to set the initial selection (as
      // determined by the proxy). _getSelection is called to get at the
      // current selection state (to send back to the server by the proxy)

      // @param source the name or ID of the tree
      // @param sel something that identifies the current selected node
      // _setSelection(source,sel)

      // @param source the name or ID of the tree
      // @return something that identifies the current selected node
      // _getSelection(source)

      //      writer.writeText
      //        ("var _treeSel = new Object();"  +
      //         "var _treeNodes = new Object();"  +
      //         "function _setSelection(source,sel) {"
      //         + "_treeSel[source]=sel;"  +
      //         "}"  +
      //         "function _getSelection(source) {"
      //         + "return _treeSel[source];"  +
      //         "}"  +
      //
      //         // _setNodes is used to indicate the number of tree nodes that are
      //         // currently visible. This is so that _clearSelection knows exactly
      //         // how many elements to clear
      //         "function _setNodes(source,nodes) {"
      //         + "_treeNodes[source]=nodes;"  +
      //         "}"  +
      //         "function _getNodes(source) {"
      //         + "return _treeNodes[source];"  +
      //         "}",
      //         null  );
      //
      //      writer.writeText
      //        ("function _select(name,index,nodeID) {"
      //         + "_clearSelection(name);"
      //         + "var e =_getElementById(document,name+index);"
      //         + "e.className = '",
      //         null  );
      //      writer.writeText(TREE_ROW_SELECTED_STYLE_CLASS+"';", null);
      //      writer.writeText
      //        ("  _setSelection(name,nodeID);return true;"  +
      //         "}",
      //         null  );
      //
      //      writer.writeText
      //        ("function _clearSelection(name) {"
      //         + "var sz = _getNodes(name);"
      //         + "for (var i = 0; i < sz; i++) {"
      //         +   "var e =_getElementById(document,name+i);"
      //         +   "e.className='",
      //         null);
      //      writer.writeText(TREE_ROW_STYLE_CLASS+"';", null);
      //      writer.writeText
      //        ("  }"  +
      //         "}",
      //         null);

      boolean immediate = getImmediate(component, bean);
      String buff =
        TreeUtils.setupJSTreeCollectionComponent(!immediate) + ";";
      writer.writeText(buff, null);
    }
  }

  // render one row of the tree

  private void _renderNode(
    FacesContext         context,
    RenderingContext     rc,
    UIXHierarchy         tree,
    FacesBean            bean,
    UIComponent          stamp,
    final String         varName,
    RowKeySet            state,
    Map<Object, Boolean> selectedPaths,
    Boolean[]            prepend,
    boolean              leftToRight,
    boolean              isFirstSibling,
    boolean              isLastSibling,
    int                  nodeDepth
    ) throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    // each row is a table
    writer.startElement(XhtmlConstants.TABLE_ELEMENT, null);
    OutputUtils.renderLayoutTableAttributes(context, rc, "0", "0", "0", null);
    writer.startElement(XhtmlConstants.TABLE_ROW_ELEMENT, null);


    // render the prepend
    _prependIcons(context, rc, tree, prepend, leftToRight);


    String onclickExpand = null;
    int expand = _getExpandValue(tree, state);

    if ((expand != NO_CHILDREN) && supportsNavigation(rc))
    {
      onclickExpand =
          TreeUtils.callJSExpandNode(tree, varName + ".treeState",
                                     (expand == EXPAND_CLOSED));
    }

    renderExpandCell(context, rc, tree, expand, isLastSibling, onclickExpand);


    //    DataObject curData = BeanAdapterUtils.getAdapter(context, tree.getRowData());
    String treeStyle = SkinSelectors.TREE_ROW_STYLE_CLASS;


    // location was a colon separated list of IDs
    //boolean selected = proxy.isSelected(context, node, location);
    Object currPath = tree.getRowKey();
    boolean selected = _isShownSelected(tree, selectedPaths, currPath);

    String onClick = _callJSSelect(tree, varName);

    //    if ( proxy.selectionEnabled(context) )
    //    {
    //      // selection with the proxy doesn't work on netscape
    //      // filed as bug 1817185 - so far we have not figured
    //      // out a way without using layers and we are seeing nodes
    //      // jump around with layers so disabling selection on netscape
    //      if ( isNetscape(context) )
    //        selected = false;
    //      else
    //      {
    //        if (supportsNavigation(context))
    //          onClick = "return _select('" + treename + "'," + renderedIndex +
    //            ",'" + location + "');";
    //      }
    //    }

    if (selected)
    {
      treeStyle = SkinSelectors.TREE_ROW_SELECTED_STYLE_CLASS;
    }

    renderNodeIconCell(context, rc, tree, expand);

    // render space between icon and node stamp
    // alt Text
    renderIconCell(context, rc, tree, null, TRANSPARENT_GIF, false, null,
                   _NODE_SPACER, _ICON_HEIGHT, null);

    // render the node stamp
    renderStampCell(context, rc, tree, stamp, onClick, treeStyle, nodeDepth);

    // end row
    writer.endElement(XhtmlConstants.TABLE_ROW_ELEMENT);
    //end table
    writer.endElement(XhtmlConstants.TABLE_ELEMENT);

    // render children
    if ((expand == EXPAND_OPEN) || (expand == EXPAND_ALWAYS))
    {
      _renderNodeChildren(context, rc, tree, bean, stamp, varName, state, selectedPaths,
                          prepend, leftToRight, isFirstSibling, isLastSibling, nodeDepth);
    }
  }

  protected void renderNodeIconCell(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    int              expand
    ) throws IOException
  {
    String nodeType = getNodeType(tree);
    Icon nodeIcon = getNodeIcon(rc, nodeType, expand);

    ResponseWriter writer = context.getResponseWriter();
    // render the node icon
    if (nodeIcon != null)
    {
      writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
      writer.writeAttribute(XhtmlConstants.WIDTH_ATTRIBUTE, _ICON_WIDTH, null);
      writer.writeAttribute(XhtmlConstants.HEIGHT_ATTRIBUTE, _ICON_HEIGHT, null);
      writer.writeAttribute(XhtmlConstants.VALIGN_ATTRIBUTE, XhtmlConstants.V_ALIGN_TOP,
                            null);

      _renderIcon(context, rc, nodeIcon.getImageURI(context, rc).toString(),
                  true, null, null, null);

      writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
    }
  }

  protected String getNodeType(
    UIXHierarchy tree)
  {
    String nodeType = null;
    Object rowData = tree.getRowData();
    Class rowClass = rowData.getClass();
    Method method;

    try
    {
      method = retrieveGetNodeTypeMethod(rowClass);
      if (method != null && method.getReturnType().equals(String.class))
      {
        nodeType = (String) method.invoke(rowData);
      }
    }
    catch (IllegalAccessException e) { ; }
    catch (InvocationTargetException e) { ; }
    return nodeType;
  }

  private Method retrieveGetNodeTypeMethod(Class rowClass)
  {
    try {
      synchronized (NODE_TYPE_METHOD_CACHE) {
        if (NODE_TYPE_METHOD_CACHE.containsKey(rowClass))
        {
          return NODE_TYPE_METHOD_CACHE.get(rowClass);
        }

        Method getNodeTypeMethod = rowClass.getMethod("getNodeType");
        NODE_TYPE_METHOD_CACHE.put(rowClass, getNodeTypeMethod);
        return getNodeTypeMethod;
      }
    } catch (Exception e)
    { return null; }

  }

  protected String getNodeIconSelector(
    String nodeType,
    int    expandedState)
  {
    switch (expandedState)
    {
      case EXPAND_OPEN:
        nodeType += NODE_ICON_EXPANDED_SUFFIX;
        break;
      case EXPAND_CLOSED:
        nodeType += NODE_ICON_COLLAPSED_SUFFIX;
        break;
    }
    return SkinSelectors.AF_TREE_NODE_ICON + ":" + nodeType;
  }

  protected Icon getNodeIcon(
    RenderingContext rc,
    String           nodeType,
    int              expandedState
  )
  {
    if (nodeType == null || nodeType.length() == 0)
    {
      return null;
    }
    Icon icon = rc.getIcon(getNodeIconSelector(nodeType, expandedState));
    if (icon == null)
      if (expandedState != NO_CHILDREN)
      {
        icon = rc.getIcon(getNodeIconSelector(nodeType, NO_CHILDREN));
      }
      else
      {
        icon = rc.getIcon(getNodeIconSelector(nodeType, EXPAND_CLOSED));
      }
    return icon;
  }


  protected void renderStampCell(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    UIComponent      stamp,
    String           onClick,
    String           treeStyle,
    int              nodeDepth
    ) throws IOException
  {
    ResponseWriter writer = context.getResponseWriter();

    writer.startElement(XhtmlConstants.TABLE_DATA_ELEMENT, null);
    writer.writeAttribute(XhtmlConstants.NOWRAP_ATTRIBUTE, Boolean.FALSE, null);
    renderStyleClass(context, rc, SkinSelectors.TREE_NODE_ADJUST_STYLE_CLASS);


    writer.startElement(XhtmlConstants.SPAN_ELEMENT, null);
    writer.writeAttribute(XhtmlConstants.ID_ATTRIBUTE, stamp.getClientId(), null);
    renderStyleClass(context, rc, treeStyle);

    if (supportsScripting(rc))
    {
      writer.writeAttribute(XhtmlConstants.ONCLICK_ATTRIBUTE, onClick, null);
    }

    // if screen reader mode render the stamp with level of node from root
    _renderStampBasedOnAccessibilty(context, rc, stamp, nodeDepth);

    writer.endElement(XhtmlConstants.SPAN_ELEMENT);
    writer.endElement(XhtmlConstants.TABLE_DATA_ELEMENT);
  }

  private void _renderNodeChildren(
    FacesContext         context,
    RenderingContext     rc,
    UIXHierarchy         tree,
    FacesBean            bean,
    UIComponent          stamp,
    final String         varName,
    RowKeySet            state,
    Map<Object, Boolean> selectedPaths,
    Boolean[]            prepend,
    boolean              leftToRight,
    boolean              isFirstSibling,
    boolean              isLastSibling,
    int                  nodeDepth
    ) throws IOException
  {
    tree.enterContainer();
    int childCount = tree.getRowCount();

    if (childCount > 0)
    {
      // prepare the prepended icons for the child nodes
      prepend = _appendIcon(prepend, (isLastSibling) ? Boolean.FALSE : Boolean.TRUE);
      Boolean[] currClone;

      ++nodeDepth; // increment the depth of the child from the root

      int oldIndex = tree.getRowIndex();
      for (int i = 0; i < childCount; i++)
      {
        currClone = new Boolean[prepend.length];
        System.arraycopy(prepend, 0, currClone, 0, prepend.length);

        tree.setRowIndex(i);
        _renderNode(context, rc, tree, bean, stamp, varName, state,
                    selectedPaths, currClone, leftToRight, i == 0,
                    (i == childCount - 1), nodeDepth);
      }
      tree.setRowIndex(oldIndex);
      --nodeDepth;
    }
    tree.exitContainer();
  }

  // is this row childless, open, or closed?

  private int _getExpandValue(
    UIXHierarchy tree,
    RowKeySet    state)
  {
    if (tree.isContainer())
    {
      if (state.isContained())
        return EXPAND_OPEN;
      else
        return EXPAND_CLOSED;
    }

    return NO_CHILDREN;
  }

  // render an icon with our own special formatting

  private void _renderIcon(
    FacesContext     context,
    RenderingContext rc,
    String           icon,
    boolean          isIconAbsoluteURI,
    Object           text,
    String           width,
    String           height
    ) throws IOException
  {
    if (icon != null)
    {
      ResponseWriter writer = context.getResponseWriter();

      // TODO: change
      writer.startElement("img", null);
      renderStyleClass(context, rc, SkinSelectors.TREE_ICON_STYLE_CLASS);
      if (width != null)
        writer.writeAttribute(XhtmlConstants.WIDTH_ATTRIBUTE, width, null);
      if (height != null)
        writer.writeAttribute(XhtmlConstants.HEIGHT_ATTRIBUTE, height, null);

      // Convert iconURL to an absolute uri
      if (!isIconAbsoluteURI)
        icon = getAbsoluteImageUri(context, rc, icon);

      renderEncodedResourceURI(context, "src", icon);

      // Ensure that we're never rendering null;  see bug 4161181
      // why this logic is not in renderAltAndTooltipForImage().
      // This is, in essence, re-introducing a more restricted version
      // of that bug.
      OutputUtils.renderAltAndTooltipForImage(context, rc, text == null? "": text);

      writer.writeAttribute("border", "0", null);
      writer.endElement("img");
    }
  }


  // add a boolean flag to the chain of icons.
  // the chain is rendered before each icon

  private Boolean[] _appendIcon(
    Boolean[] prepend,
    Boolean   isLine)
  {
    int currLength = prepend.length;

    if (prepend[currLength - 1] != null)
    {
      // resize, incrementing should be fine
      Boolean[] newBools =
        new Boolean[currLength + _DEFAULT_TREE_INCREMENT];
      System.arraycopy(prepend, 0, newBools, 0, currLength);
      prepend = newBools;
    }

    for (int i = 0; i < currLength; i++)
    {
      if (prepend[i] == null)
      {
        prepend[i] = isLine;
        break;
      }
    }

    return prepend;
  }


  private void _prependIcons(
    FacesContext     context,
    RenderingContext rc,
    UIXHierarchy     tree,
    Boolean[]        prepend,
    boolean          leftToRight
    ) throws IOException
  {
    int currLength = prepend.length;
    Boolean isLine;

    for (int i = 0; i < currLength; i++)
    {
      isLine = prepend[i];

      if (isLine != null)
      {
        String icon = TRANSPARENT_GIF;

        String backgroundIcon =
            getConnectingBackgroundIcon(context, rc, isLine.booleanValue(), leftToRight);

        // alt text
        renderIconCell(context, rc, tree, backgroundIcon, icon, false, null,
                       _ICON_WIDTH, "100%", null);
      }
    }
  }

  protected boolean getImmediate(
    UIComponent component,
    FacesBean   bean)
  {
    Object o = bean.getProperty(_immediateKey);
    if (o == null)
      o = _immediateKey.getDefault();

    return Boolean.TRUE.equals(o);
  }

  protected String getDefaultIconName()
  {
    return null;
  }

  private void _renderStampBasedOnAccessibilty(
    FacesContext     context,
    RenderingContext rc,
    UIComponent      stamp,
    int              depth
    ) throws IOException
  {
    if (isScreenReaderMode(rc))
    {
      RenderingContext arc = RenderingContext.getCurrentInstance();
      FacesContext fc = FacesContext.getCurrentInstance();
      if (rc.isRightToLeft())
      {
        //TODO: do we need default stamp support???
        encodeChild(context, stamp);
        TreeUtils.writeNodeLevel(fc, arc, depth, _NODE_LEVEL_TEXT_KEY);
      }
      else
      {
        TreeUtils.writeNodeLevel(fc, arc, depth, _NODE_LEVEL_TEXT_KEY);
        encodeChild(context, stamp);
      }
    }
    else
      encodeChild(context, stamp);
  }

  private static final String _BACKGROUND_IMAGE_URL =
    "background-image:url(";
  private static final String _END_FUNC = ");";
  private static final String _BACKGROUND_NO_REPEAT = "background-repeat:no-repeat;";

  private static final String _ICON_WIDTH = "19";
  private static final String _ICON_HEIGHT = "18";
  private static final String _NODE_SPACER = "3";

  // expanded states
  protected static final int NO_CHILDREN = 0;
  protected static final int EXPAND_CLOSED = 1;
  protected static final int EXPAND_OPEN = 2;
  protected static final int EXPAND_ALWAYS = 3;

  // prepend chain constants
  private static final int _DEFAULT_TREE_DEPTH = 10;
  private static final int _DEFAULT_TREE_INCREMENT = 5;

  // =-= ACW: this key is used to make sure that certain javascript functions
  // used by this renderer, are rendered only once per render cycle.
  private static final Object _JS_RENDERED_KEY = new Object();

  // Key used by StyledTextBean to query style class
  static final String _STYLE_CLASS_KEY = "_styleClass";

  private final Map<Class<?>, Method> NODE_TYPE_METHOD_CACHE = new HashMap<Class<?>, Method>();
  private PropertyKey _immediateKey;

  // translation keys
  private static final String _DISABLED_COLLAPSE_TIP_KEY =
    "af_tree.DISABLED_COLLAPSE_TIP";
  private static final String _COLLAPSE_TIP_KEY = "af_tree.COLLAPSE_TIP";
  private static final String _EXPAND_TIP_KEY = "af_tree.EXPAND_TIP";
  private static final String _NODE_LEVEL_TEXT_KEY = "af_tree.NODE_LEVEL";

  private static final String _PATH_PARAM = "path";
  public static final String SELECTED_PARAM = "_selected";

  public static final String NODE_ICON_EXPANDED_SUFFIX = "-expanded";
  public static final String NODE_ICON_COLLAPSED_SUFFIX = "-collapsed";

  private static final TrinidadLogger _LOG =
    TrinidadLogger.createTrinidadLogger(TreeRenderer.class);
}
