/*
 * 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.view.facelets.component;

import java.io.IOException;
import java.io.Serializable;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.component.ContextCallback;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIComponentBase;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.component.visit.VisitResult;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.FacesListener;
import javax.faces.event.PhaseId;
import javax.faces.model.ArrayDataModel;
import javax.faces.model.CollectionDataModel;
import javax.faces.model.DataModel;
import javax.faces.model.ListDataModel;
import javax.faces.model.ResultSetDataModel;
import javax.faces.model.ScalarDataModel;
import javax.faces.render.Renderer;

import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;

/**
 *  
 */
@JSFComponent(name="ui:repeat", defaultRendererType="facelets.ui.Repeat")
public class UIRepeat extends UIComponentBase implements NamingContainer
{
    public static final String COMPONENT_TYPE = "facelets.ui.Repeat";

    public static final String COMPONENT_FAMILY = "facelets";
    
    //private static final String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";

    private final static DataModel<?> EMPTY_MODEL = new ListDataModel<Object>(Collections.emptyList());
    
    private static final Class<Object[]> OBJECT_ARRAY_CLASS = Object[].class;

    private static final Object[] LEAF_NO_STATE = new Object[]{null,null};
    
    private Object _initialDescendantComponentState = null;

    // Holds for each row the states of the child components of this UIData.
    // Note that only "partial" component state is saved: the component fields
    // that are expected to vary between rows.
    private Map<String, Collection<Object[]>> _rowStates = new HashMap<String, Collection<Object[]>>();
    
    /**
     * Handle case where this table is nested inside another table. See method getDataModel for more details.
     * <p>
     * Key: parentClientId (aka rowId when nested within a parent table) Value: DataModel
     */
    private Map<String, DataModel> _dataModelMap = new HashMap<String, DataModel>();
    
    // will be set to false if the data should not be refreshed at the beginning of the encode phase
    private boolean _isValidChilds = true;

    private int _end = -1;
    
    private int _count;
    
    private int _index = -1;

    private transient StringBuilder _clientIdBuffer;
    private transient Object _origValue;
    private transient Object _origVarStatus;

    private transient FacesContext _facesContext;
    
    static final Integer RESET_MODE_OFF = 0;
    static final Integer RESET_MODE_SOFT = 1;
    static final Integer RESET_MODE_HARD = 2;    
    
    public UIRepeat()
    {
        setRendererType("facelets.ui.Repeat");
    }

    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }
    
    @JSFProperty
    public int getOffset()
    {
        return (Integer) getStateHelper().eval(PropertyKeys.offset, 0);
    }

    public void setOffset(int offset)
    {
        getStateHelper().put(PropertyKeys.offset, offset );
    }
    
    @JSFProperty
    public int getSize()
    {
        return (Integer) getStateHelper().eval(PropertyKeys.size, -1);
    }

    public void setSize(int size)
    {
        getStateHelper().put(PropertyKeys.size, size );
    }
    
    @JSFProperty
    public int getStep()
    {
        return (Integer) getStateHelper().eval(PropertyKeys.step, 1);
    }

    public void setStep(int step)
    {
        getStateHelper().put(PropertyKeys.step, step );
    }
    
    @JSFProperty(literalOnly=true)
    public String getVar()
    {
        return (String) getStateHelper().get(PropertyKeys.var);
    }

    public void setVar(String var)
    {
        getStateHelper().put(PropertyKeys.var, var );
    }
    
    @JSFProperty(literalOnly=true)
    public String getVarStatus ()
    {
        return (String) getStateHelper().get(PropertyKeys.varStatus);
    }
    
    public void setVarStatus (String varStatus)
    {
        getStateHelper().put(PropertyKeys.varStatus, varStatus );
    }
    
    protected DataModel getDataModel()
    {
        DataModel dataModel;
        String clientID = "";

        UIComponent parent = getParent();
        if (parent != null)
        {
            clientID = parent.getContainerClientId(getFacesContext());
        }
        dataModel = _dataModelMap.get(clientID);
        if (dataModel == null)
        {
            dataModel = createDataModel();
            _dataModelMap.put(clientID, dataModel);
        }
        return dataModel;
    }
    
    private DataModel createDataModel()
    {
        Object value = getValue();

        if (value == null)
        {
            return EMPTY_MODEL;
        }
        else if (value instanceof DataModel)
        {
            return (DataModel) value;
        }
        else if (value instanceof List)
        {
            return new ListDataModel((List<?>) value);
        }
        else if (OBJECT_ARRAY_CLASS.isAssignableFrom(value.getClass()))
        {
            return new ArrayDataModel((Object[]) value);
        }
        else if (value instanceof ResultSet)
        {
            return new ResultSetDataModel((ResultSet) value);
        }
        else if (value instanceof Collection)
        {
            return new CollectionDataModel((Collection) value);
        }
        else
        {
            return new ScalarDataModel(value);
        }
    }
    
    @Override
    public void setValueExpression(String name, ValueExpression binding)
    {
        if (name == null)
        {
            throw new NullPointerException("name");
        }
        else if (name.equals("value"))
        {
            _dataModelMap.clear();
        }
        else if (name.equals("rowIndex"))
        {
            throw new IllegalArgumentException("name " + name);
        }
        super.setValueExpression(name, binding);
    }
    
    @JSFProperty
    public Object getValue()
    {
        return  getStateHelper().eval(PropertyKeys.value);
    }

    public void setValue(Object value)
    {
        getStateHelper().put(PropertyKeys.value, value);
        _dataModelMap.clear();
        _rowStates.clear();
        _isValidChilds = true;
    }

    @Override
    public String getContainerClientId(FacesContext context)
    {
        //MYFACES-2744 UIData.getClientId() should not append rowIndex, instead use UIData.getContainerClientId()
        String clientId = super.getContainerClientId(context);
        
        int index = getIndex();
        if (index == -1)
        {
            return clientId;
        }

        StringBuilder bld = _getBuffer(); //SharedStringBuilder(context);
        return bld.append(clientId).append(context.getNamingContainerSeparatorChar()).append(index).toString();
    }
    
    private RepeatStatus _getRepeatStatus()
    {
        return new RepeatStatus(_count == 0, _index + getStep() >= getDataModel().getRowCount(),
            _count, _index, getOffset(), _end, getStep());
    }

    private void _captureScopeValues()
    {
        String var = getVar();
        if (var != null)
        {
            _origValue = getFacesContext().getExternalContext().getRequestMap().get(var);
        }
        String varStatus = getVarStatus();
        if (varStatus != null)
        {
            _origVarStatus = getFacesContext().getExternalContext().getRequestMap().get(varStatus);
        }
    }
    
    private StringBuilder _getBuffer()
    {
        if (_clientIdBuffer == null)
        {
            _clientIdBuffer = new StringBuilder();
        }
        
        _clientIdBuffer.setLength(0);
        
        return _clientIdBuffer;
    }

    private boolean _isIndexAvailable()
    {
        return getDataModel().isRowAvailable();
    }

    private void _restoreScopeValues()
    {
        String var = getVar();
        if (var != null)
        {
            Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
            if (_origValue != null)
            {
                attrs.put(var, _origValue);
                _origValue = null;
            }
            else
            {
                attrs.remove(var);
            }
        }
        String varStatus = getVarStatus();
        if (getVarStatus() != null)
        {
            Map<String, Object> attrs = getFacesContext().getExternalContext().getRequestMap();
            if (_origVarStatus != null)
            {
                attrs.put(varStatus, _origVarStatus);
                _origVarStatus = null;
            }
            else
            {
                attrs.remove(varStatus);
            }
        }
    }
    
    /**
     * Overwrite the state of the child components of this component with data previously saved by method
     * saveDescendantComponentStates.
     * <p>
     * The saved state info only covers those fields that are expected to vary between rows of a table. 
     * Other fields are not modified.
     */
    @SuppressWarnings("unchecked")
    private void restoreDescendantComponentStates(UIComponent parent, boolean iterateFacets, Object state,
                                                  boolean restoreChildFacets)
    {
        int descendantStateIndex = -1;
        List<? extends Object[]> stateCollection = null;
        
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
            
            while (childIterator.hasNext())
            {
                UIComponent component = childIterator.next();

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    if (descendantStateIndex == -1)
                    {
                        stateCollection = ((List<? extends Object[]>) state);
                        descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
                    }
                    
                    if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
                    {
                        Object[] object = stateCollection.get(descendantStateIndex);
                        if (object[0] != null && component instanceof EditableValueHolder)
                        {
                            ((SavedState) object[0]).restoreState((EditableValueHolder) component);
                        }
                        // If there is descendant state to restore, call it recursively, otherwise
                        // it is safe to skip iteration.
                        if (object[1] != null)
                        {
                            restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
                        }
                        else
                        {
                            restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                        }
                    }
                    else
                    {
                        restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                    }
                    descendantStateIndex++;
                }
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent component = parent.getChildren().get(i);

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    if (descendantStateIndex == -1)
                    {
                        stateCollection = ((List<? extends Object[]>) state);
                        descendantStateIndex = stateCollection.isEmpty() ? -1 : 0;
                    }
                    
                    if (descendantStateIndex != -1 && descendantStateIndex < stateCollection.size())
                    {
                        Object[] object = stateCollection.get(descendantStateIndex);
                        if (object[0] != null && component instanceof EditableValueHolder)
                        {
                            ((SavedState) object[0]).restoreState((EditableValueHolder) component);
                        }
                        // If there is descendant state to restore, call it recursively, otherwise
                        // it is safe to skip iteration.
                        if (object[1] != null)
                        {
                            restoreDescendantComponentStates(component, restoreChildFacets, object[1], true);
                        }
                        else
                        {
                            restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                        }
                    }
                    else
                    {
                        restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                    }
                    descendantStateIndex++;
                }
            }
        }
    }

    /**
     * Just call component.setId(component.getId()) to reset all client ids and 
     * ensure they will be calculated for the current row, but do not waste time
     * dealing with row state code.
     * 
     * @param parent
     * @param iterateFacets
     * @param restoreChildFacets 
     */
    private void restoreDescendantComponentWithoutRestoreState(UIComponent parent, boolean iterateFacets,
                                                               boolean restoreChildFacets)
    {
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();
            
            while (childIterator.hasNext())
            {
                UIComponent component = childIterator.next();

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                }
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent component = parent.getChildren().get(i);

                // reset the client id (see spec 3.1.6)
                component.setId(component.getId());
                if (!component.isTransient())
                {
                    restoreDescendantComponentWithoutRestoreState(component, restoreChildFacets, true);
                }
            }
        }
    }

    /**
     * Walk the tree of child components of this UIData, saving the parts of their state that can vary between rows.
     * <p>
     * This is very similar to the process that occurs for normal components when the view is serialized. Transient
     * components are skipped (no state is saved for them).
     * <p>
     * If there are no children then null is returned. If there are one or more children, and all children are transient
     * then an empty collection is returned; this will happen whenever a table contains only read-only components.
     * <p>
     * Otherwise a collection is returned which contains an object for every non-transient child component; that object
     * may itself contain a collection of the state of that child's child components.
     */
    private Collection<Object[]> saveDescendantComponentStates(UIComponent parent, boolean iterateFacets,
                                                               boolean saveChildFacets)
    {
        Collection<Object[]> childStates = null;
        // Index to indicate how many components has been passed without state to save.
        int childEmptyIndex = 0;
        int totalChildCount = 0;
                
        if (iterateFacets && parent.getFacetCount() > 0)
        {
            Iterator<UIComponent> childIterator = parent.getFacets().values().iterator();

            while (childIterator.hasNext())
            {
                UIComponent child = childIterator.next();
                if (!child.isTransient())
                {
                    // Add an entry to the collection, being an array of two
                    // elements. The first element is the state of the children
                    // of this component; the second is the state of the current
                    // child itself.

                    if (child instanceof EditableValueHolder)
                    {
                        if (childStates == null)
                        {
                            childStates = new ArrayList<Object[]>(
                                    parent.getFacetCount()
                                    + parent.getChildCount()
                                    - totalChildCount
                                    + childEmptyIndex);
                            for (int ci = 0; ci < childEmptyIndex; ci++)
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                    
                        childStates.add(child.getChildCount() > 0 ? 
                                new Object[]{new SavedState((EditableValueHolder) child),
                                    saveDescendantComponentStates(child, saveChildFacets, true)} :
                                new Object[]{new SavedState((EditableValueHolder) child),
                                    null});
                    }
                    else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
                    {
                        Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
                        
                        if (descendantSavedState == null)
                        {
                            if (childStates == null)
                            {
                                childEmptyIndex++;
                            }
                            else
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                        else
                        {
                            if (childStates == null)
                            {
                                childStates = new ArrayList<Object[]>(
                                        parent.getFacetCount()
                                        + parent.getChildCount()
                                        - totalChildCount
                                        + childEmptyIndex);
                                for (int ci = 0; ci < childEmptyIndex; ci++)
                                {
                                    childStates.add(LEAF_NO_STATE);
                                }
                            }
                            childStates.add(new Object[]{null, descendantSavedState});
                        }
                    }
                    else
                    {
                        if (childStates == null)
                        {
                            childEmptyIndex++;
                        }
                        else
                        {
                            childStates.add(LEAF_NO_STATE);
                        }
                    }
                }
                totalChildCount++;
            }
        }
        
        if (parent.getChildCount() > 0)
        {
            for (int i = 0; i < parent.getChildCount(); i++)
            {
                UIComponent child = parent.getChildren().get(i);
                if (!child.isTransient())
                {
                    // Add an entry to the collection, being an array of two
                    // elements. The first element is the state of the children
                    // of this component; the second is the state of the current
                    // child itself.

                    if (child instanceof EditableValueHolder)
                    {
                        if (childStates == null)
                        {
                            childStates = new ArrayList<Object[]>(
                                    parent.getFacetCount()
                                    + parent.getChildCount()
                                    - totalChildCount
                                    + childEmptyIndex);
                            for (int ci = 0; ci < childEmptyIndex; ci++)
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                    
                        childStates.add(child.getChildCount() > 0 ? 
                                new Object[]{new SavedState((EditableValueHolder) child),
                                    saveDescendantComponentStates(child, saveChildFacets, true)} :
                                new Object[]{new SavedState((EditableValueHolder) child),
                                    null});
                    }
                    else if (child.getChildCount() > 0 || (saveChildFacets && child.getFacetCount() > 0))
                    {
                        Object descendantSavedState = saveDescendantComponentStates(child, saveChildFacets, true);
                        
                        if (descendantSavedState == null)
                        {
                            if (childStates == null)
                            {
                                childEmptyIndex++;
                            }
                            else
                            {
                                childStates.add(LEAF_NO_STATE);
                            }
                        }
                        else
                        {
                            if (childStates == null)
                            {
                                childStates = new ArrayList<Object[]>(
                                        parent.getFacetCount()
                                        + parent.getChildCount()
                                        - totalChildCount
                                        + childEmptyIndex);
                                for (int ci = 0; ci < childEmptyIndex; ci++)
                                {
                                    childStates.add(LEAF_NO_STATE);
                                }
                            }
                            childStates.add(new Object[]{null, descendantSavedState});
                        }
                    }
                    else
                    {
                        if (childStates == null)
                        {
                            childEmptyIndex++;
                        }
                        else
                        {
                            childStates.add(LEAF_NO_STATE);
                        }
                    }
                }
                totalChildCount++;
            }
        }
        
        return childStates;
    }
    
    /**
     * Returns the rowCount of the underlying DataModel.
     * @return
     */
    public int getRowCount()
    {
        return getDataModel().getRowCount();
    }
    
    /**
     * Returns the current index.
     */
    public int getIndex()
    {
        return _index;
    }
    
    public void setRowIndex(int index)
    {
        _setIndex(index);
    }
    
    private void _setIndex(int index)
    {
        // save child state
        //_saveChildState();
        if (index < -1)
        {
            throw new IllegalArgumentException("rowIndex is less than -1");
        }

        if (_index == index)
        {
            return;
        }

        FacesContext facesContext = getFacesContext();

        if (_index == -1)
        {
            if (_initialDescendantComponentState == null)
            {
                // Create a template that can be used to initialise any row
                // that we haven't visited before, ie a "saved state" that can
                // be pushed to the "restoreState" method of all the child
                // components to set them up to represent a clean row.
                _initialDescendantComponentState = saveDescendantComponentStates(this, true, true);
            }
        }
        else
        {
            // If no initial component state, there are no EditableValueHolder instances,
            // and that means there is no state to be saved for the current row, so we can
            // skip row state saving code safely.
            if (_initialDescendantComponentState != null)
            {
                // We are currently positioned on some row, and are about to
                // move off it, so save the (partial) state of the components
                // representing the current row. Later if this row is revisited
                // then we can restore this state.
                Collection<Object[]> savedRowState = saveDescendantComponentStates(this, true, true);
                if (savedRowState != null)
                {
                    _rowStates.put(getContainerClientId(facesContext), savedRowState);
                }
            }
        }

        _index = index;
        
        DataModel<?> localModel = getDataModel();
        localModel.setRowIndex(index);

        if (_index != -1)
        {
            String var = getVar();
            if (var != null && localModel.isRowAvailable())
            {
                getFacesContext().getExternalContext().getRequestMap()
                        .put(var, localModel.getRowData());
            }
            String varStatus = getVarStatus();
            if (varStatus != null)
            {
                getFacesContext().getExternalContext().getRequestMap()
                        .put(varStatus, _getRepeatStatus());
            }
        }

        // restore child state
        //_restoreChildState();
        
        if (_index == -1)
        {
            // reset components to initial state
            // If no initial state, skip row restore state code
            if (_initialDescendantComponentState != null)
            {
                restoreDescendantComponentStates(this, true, _initialDescendantComponentState, true);
            }
            else
            {
                restoreDescendantComponentWithoutRestoreState(this, true, true);
            }
        }
        else
        {
            Object rowState = _rowStates.get(getContainerClientId(facesContext));
            if (rowState == null)
            {
                // We haven't been positioned on this row before, so just
                // configure the child components of this component with
                // the standard "initial" state
                // If no initial state, skip row restore state code
                if (_initialDescendantComponentState != null)
                {
                    restoreDescendantComponentStates(this, true, _initialDescendantComponentState, true);
                }
                else
                {
                    restoreDescendantComponentWithoutRestoreState(this, true, true);
                }
            }
            else
            {
                // We have been positioned on this row before, so configure
                // the child components of this component with the (partial)
                // state that was previously saved. Fields not in the
                // partial saved state are left with their original values.
                restoreDescendantComponentStates(this, true, rowState, true);
            }
        }
    }
    
    /**
     * Calculates the count value for the given index.
     * @param index
     * @return
     */
    private int _calculateCountForIndex(int index)
    {
        return (index - getOffset()) / getStep();
    }

    private void _validateAttributes() throws FacesException
    {
        int begin = getOffset();
        int end = getDataModel().getRowCount();
        int size = getSize();
        int step = getStep();
        boolean sizeIsEnd = false;

        if (size == -1)
        {
            size = end;
            sizeIsEnd = true;
        }

        if (end >= 0)
        {
            if (size < 0)
            {
                throw new FacesException("iteration size cannot be less " +
                        "than zero");
            }

            else if (!sizeIsEnd && (begin + size) > end)
            {
                throw new FacesException("iteration size cannot be greater " +
                        "than collection size");
            }
        }

        if ((size > -1) && (begin > end))
        {
            throw new FacesException("iteration offset cannot be greater " +
                    "than collection size");
        }

        if (step == -1)
        {
            setStep(1);
        }

        if (step < 0)
        {
            throw new FacesException("iteration step size cannot be less " +
                    "than zero");
        }

        else if (step == 0)
        {
            throw new FacesException("iteration step size cannot be equal " +
                    "to zero");
        }

        _end = size;
        //_step = step;
    }

    public void process(FacesContext faces, PhaseId phase)
    {
        // stop if not rendered
        if (!isRendered())
        {
            return;
        }
        
        // validate attributes
        _validateAttributes();
        
        // reset index
        _captureScopeValues();
        _setIndex(-1);

        try
        {
            // has children
            if (getChildCount() > 0)
            {
                int i = getOffset();
                int end = getSize();
                int step = getStep();
                end = (end >= 0) ? i + end : Integer.MAX_VALUE - 1;
                
                // grab renderer
                String rendererType = getRendererType();
                Renderer renderer = null;
                if (rendererType != null)
                {
                    renderer = getRenderer(faces);
                }
                
                _count = 0;
                
                _setIndex(i);
                while (i < end && _isIndexAvailable())
                {

                    if (PhaseId.RENDER_RESPONSE.equals(phase) && renderer != null)
                    {
                        renderer.encodeChildren(faces, this);
                    }
                    else
                    {
                        for (int j = 0, childCount = getChildCount(); j < childCount; j++)
                        {
                            UIComponent child = getChildren().get(j);
                            if (PhaseId.APPLY_REQUEST_VALUES.equals(phase))
                            {
                                child.processDecodes(faces);
                            }
                            else if (PhaseId.PROCESS_VALIDATIONS.equals(phase))
                            {
                                child.processValidators(faces);
                            }
                            else if (PhaseId.UPDATE_MODEL_VALUES.equals(phase))
                            {
                                child.processUpdates(faces);
                            }
                            else if (PhaseId.RENDER_RESPONSE.equals(phase))
                            {
                                child.encodeAll(faces);
                            }
                        }
                    }
                    
                    ++_count;
                    
                    i += step;
                    
                    _setIndex(i);
                }
            }
        }
        catch (IOException e)
        {
            throw new FacesException(e);
        }
        finally
        {
            _setIndex(-1);
            _restoreScopeValues();
        }
    }

    @Override
    public boolean invokeOnComponent(FacesContext context, String clientId,
            ContextCallback callback) throws FacesException
    {
        if (context == null || clientId == null || callback == null)
        {
            throw new NullPointerException();
        }
        
        final String baseClientId = getClientId(context);

        // searching for this component?
        boolean returnValue = baseClientId.equals(clientId);

        boolean isCachedFacesContext = isTemporalFacesContext();
        if (!isCachedFacesContext)
        {
            setTemporalFacesContext(context);
        }

        pushComponentToEL(context, this);
        try
        {
            if (returnValue)
            {
                try
                {
                    callback.invokeContextCallback(context, this);
                    return true;
                }
                catch (Exception e)
                {
                    throw new FacesException(e);
                }
            }
    
            // Now Look throught facets on this UIComponent
            if (this.getFacetCount() > 0)
            {
                for (Iterator<UIComponent> it = this.getFacets().values().iterator(); !returnValue && it.hasNext();)
                {
                    returnValue = it.next().invokeOnComponent(context, clientId, callback);
                }
            }
    
            if (returnValue)
            {
                return returnValue;
            }
            
            // is the component an inner component?
            if (clientId.startsWith(baseClientId))
            {
                // Check if the clientId for the component, which we 
                // are looking for, has a rowIndex attached
                char separator = context.getNamingContainerSeparatorChar();
                String subId = clientId.substring(baseClientId.length() + 1);
                //If the char next to baseClientId is the separator one and
                //the subId matches the regular expression
                if (clientId.charAt(baseClientId.length()) == separator && 
                        subId.matches("[0-9]+"+separator+".*"))
                {
                    String clientRow = subId.substring(0, subId.indexOf(separator));
        
                    // safe the current index, count aside
                    final int prevIndex = _index;
                    final int prevCount = _count;
                    
                    try
                    {
                        int invokeIndex = Integer.parseInt(clientRow);
                        // save the current scope values and set the right index
                        _captureScopeValues();
                        if (invokeIndex != -1)
                        {
                            // calculate count for RepeatStatus
                            _count = _calculateCountForIndex(invokeIndex);
                        }
                        _setIndex(invokeIndex);
                        
                        if (!_isIndexAvailable())
                        {
                            return false;
                        }
                        
                        for (Iterator<UIComponent> it1 = getChildren().iterator(); 
                            !returnValue && it1.hasNext();)
                        {
                            //recursive call to find the component
                            returnValue = it1.next().invokeOnComponent(context, clientId, callback);
                        }
                    }
                    finally
                    {
                        // restore the previous count, index and scope values
                        _count = prevCount;
                        _setIndex(prevIndex);
                        _restoreScopeValues();
                    }
                }
                else
                {
                    // Searching for this component's children
                    if (this.getChildCount() > 0)
                    {
                        // Searching for this component's children/facets
                        for (Iterator<UIComponent> it = this.getChildren().iterator(); !returnValue && it.hasNext();)
                        {
                            returnValue = it.next().invokeOnComponent(context, clientId, callback);
                        }
                    }
                }
            }
        }
        finally
        {
            //all components must call popComponentFromEl after visiting is finished
            popComponentFromEL(context);
            if (!isCachedFacesContext)
            {
                setTemporalFacesContext(null);
            }
        }

        return returnValue;
    }
    
    @Override
    protected FacesContext getFacesContext()
    {
        if (_facesContext == null)
        {
            return super.getFacesContext();
        }
        else
        {
            return _facesContext;
        }
    }
    
    private boolean isTemporalFacesContext()
    {
        return _facesContext != null;
    }
    
    private void setTemporalFacesContext(FacesContext facesContext)
    {
        _facesContext = facesContext;
    }

    @Override
    public boolean visitTree(VisitContext context, VisitCallback callback)
    {
        // override the behavior from UIComponent to visit
        // all children once per "row"
        
        //(Boolean) context.getFacesContext().getAttributes().get(SKIP_ITERATION_HINT);
        Boolean skipIterationHint = context.getHints().contains(VisitHint.SKIP_ITERATION);
        if (skipIterationHint != null && skipIterationHint.booleanValue())
        {
            return super.visitTree(context, callback);
        }
        
        if (!isVisitable(context)) 
        {
            return false;
        }
        
        // save the current index, count aside
        final int prevIndex = _index;
        final int prevCount = _count;
        
        // validate attributes
        _validateAttributes();
        
        // reset index and save scope values
        _captureScopeValues();
        _setIndex(-1);
        
        // push the Component to EL
        pushComponentToEL(context.getFacesContext(), this);
        try 
        {
            VisitResult res = context.invokeVisitCallback(this, callback);
            switch (res) 
            {
            // we are done, nothing has to be processed anymore
            case COMPLETE:
                return true;

            case REJECT:
                return false;

            //accept
            default:
                // determine if we need to visit our children
                // Note that we need to do this check because we are a NamingContainer
                Collection<String> subtreeIdsToVisit = context
                        .getSubtreeIdsToVisit(this);
                boolean doVisitChildren = subtreeIdsToVisit != null
                        && !subtreeIdsToVisit.isEmpty();
                if (doVisitChildren)
                {
                    // visit the facets of the component
                    if (getFacetCount() > 0) 
                    {
                        for (UIComponent facet : getFacets().values()) 
                        {
                            if (facet.visitTree(context, callback)) 
                            {
                                return true;
                            }
                        }
                    }
                    
                    // visit the children once per "row"
                    if (getChildCount() > 0) 
                    {
                        int i = getOffset();
                        int end = getSize();
                        int step = getStep();
                        end = (end >= 0) ? i + end : Integer.MAX_VALUE - 1;
                        _count = 0;
                        
                        _setIndex(i);
                        while (i < end && _isIndexAvailable())
                        {
                            for (int j = 0, childCount = getChildCount(); j < childCount; j++)
                            {
                                UIComponent child = getChildren().get(j);
                                if (child.visitTree(context, callback)) 
                                {
                                    return true;
                                }
                            }
                            
                            _count++;
                            i += step;
                            
                            _setIndex(i);
                        }
                    }
                }
                return false;
            }
        }
        finally 
        {
            // pop the component from EL
            popComponentFromEL(context.getFacesContext());
            
            // restore the previous count, index and scope values
            _count = prevCount;
            _setIndex(prevIndex);
            _restoreScopeValues();
        }
    }

    @Override
    public void processDecodes(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
        
        process(faces, PhaseId.APPLY_REQUEST_VALUES);
        decode(faces);
    }

    @Override
    public void processUpdates(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
        
        process(faces, PhaseId.UPDATE_MODEL_VALUES);
        
        if (faces.getRenderResponse())
        {
            _isValidChilds = false;
        }
    }

    @Override
    public void processValidators(FacesContext faces)
    {
        if (!isRendered())
        {
            return;
        }
        
        process(faces, PhaseId.PROCESS_VALIDATIONS);
        
        // check if an validation error forces the render response for our data
        if (faces.getRenderResponse())
        {
            _isValidChilds = false;
        }
    }

    // from RI
    private final static class SavedState implements Serializable
    {
        private boolean _localValueSet;
        private Object _submittedValue;
        private boolean _valid = true;
        private Object _value;

        private static final long serialVersionUID = 2920252657338389849L;
        
        public SavedState(EditableValueHolder evh)
        {
            _value = evh.getLocalValue();
            _localValueSet = evh.isLocalValueSet();
            _valid = evh.isValid();
            _submittedValue = evh.getSubmittedValue();
        }        

        Object getSubmittedValue()
        {
            return (_submittedValue);
        }

        void setSubmittedValue(Object submittedValue)
        {
            _submittedValue = submittedValue;
        }

        boolean isValid()
        {
            return (_valid);
        }

        void setValid(boolean valid)
        {
            _valid = valid;
        }

        Object getValue()
        {
            return _value;
        }

        public void setValue(Object value)
        {
            _value = value;
        }

        boolean isLocalValueSet()
        {
            return _localValueSet;
        }

        public void setLocalValueSet(boolean localValueSet)
        {
            _localValueSet = localValueSet;
        }

        @Override
        public String toString()
        {
            return ("submittedValue: " + _submittedValue + " value: " + _value + " localValueSet: " + _localValueSet);
        }
        
        public void restoreState(EditableValueHolder evh)
        {
            evh.setValue(_value);
            evh.setValid(_valid);
            evh.setSubmittedValue(_submittedValue);
            evh.setLocalValueSet(_localValueSet);
        }

        public void populate(EditableValueHolder evh)
        {
            _value = evh.getLocalValue();
            _valid = evh.isValid();
            _submittedValue = evh.getSubmittedValue();
            _localValueSet = evh.isLocalValueSet();
        }

        public void apply(EditableValueHolder evh)
        {
            evh.setValue(_value);
            evh.setValid(_valid);
            evh.setSubmittedValue(_submittedValue);
            evh.setLocalValueSet(_localValueSet);
        }
    }

    private final class IndexedEvent extends FacesEvent
    {
        private final FacesEvent _target;

        private final int _index;

        public IndexedEvent(UIRepeat owner, FacesEvent target, int index)
        {
            super(owner);
            _target = target;
            _index = index;
        }

        @Override
        public PhaseId getPhaseId()
        {
            return _target.getPhaseId();
        }

        @Override
        public void setPhaseId(PhaseId phaseId)
        {
            _target.setPhaseId(phaseId);
        }

        public boolean isAppropriateListener(FacesListener listener)
        {
            return _target.isAppropriateListener(listener);
        }

        public void processListener(FacesListener listener)
        {
            UIRepeat owner = (UIRepeat) getComponent();
            
            // safe the current index, count aside
            final int prevIndex = owner._index;
            final int prevCount = owner._count;
            
            try
            {
                owner._captureScopeValues();
                if (this._index != -1)
                {
                    // calculate count for RepeatStatus
                    _count = _calculateCountForIndex(this._index);
                }
                owner._setIndex(this._index);
                if (owner._isIndexAvailable())
                {
                    _target.processListener(listener);
                }
            }
            finally
            {
                // restore the previous count, index and scope values
                owner._count = prevCount;
                owner._setIndex(prevIndex);
                owner._restoreScopeValues();
            }
        }

        public int getIndex()
        {
            return _index;
        }

        public FacesEvent getTarget()
        {
            return _target;
        }

    }

    @Override
    public void broadcast(FacesEvent event) throws AbortProcessingException
    {
        if (event instanceof IndexedEvent)
        {
            IndexedEvent idxEvent = (IndexedEvent) event;
            
            // safe the current index, count aside
            final int prevIndex = _index;
            final int prevCount = _count;
            
            try
            {
                _captureScopeValues();
                if (idxEvent.getIndex() != -1)
                {
                    // calculate count for RepeatStatus
                    _count = _calculateCountForIndex(idxEvent.getIndex());
                }
                _setIndex(idxEvent.getIndex());
                if (_isIndexAvailable())
                {
                    // get the target FacesEvent
                    FacesEvent target = idxEvent.getTarget();
                    FacesContext facesContext = getFacesContext();
                    
                    // get the component associated with the target event and push
                    // it and its composite component parent, if available, to the
                    // component stack to have them available while processing the 
                    // event (see also UIViewRoot._broadcastAll()).
                    UIComponent targetComponent = target.getComponent();
                    UIComponent compositeParent = UIComponent
                            .getCompositeComponentParent(targetComponent);
                    if (compositeParent != null)
                    {
                        pushComponentToEL(facesContext, compositeParent);
                    }
                    pushComponentToEL(facesContext, targetComponent);
                    
                    try
                    {
                        // actual event broadcasting
                        targetComponent.broadcast(target);
                    }
                    finally
                    {
                        // remove the components from the stack again
                        popComponentFromEL(facesContext);
                        if (compositeParent != null)
                        {
                            popComponentFromEL(facesContext);
                        }
                    }
                }
            }
            finally
            {
                // restore the previous count, index and scope values
                _count = prevCount;
                _setIndex(prevIndex);
                _restoreScopeValues();
            }
        }
        else
        {
            super.broadcast(event);
        }
    }

    @Override
    public void queueEvent(FacesEvent event)
    {
        super.queueEvent(new IndexedEvent(this, event, _index));
    }

    @Override
    public void restoreState(FacesContext context, Object state)
    {
        if (state == null)
        {
            return;
        }
        
        Object values[] = (Object[]) state;
        super.restoreState(context, values[0]);
        //Object restoredRowStates = UIComponentBase.restoreAttachedState(context, values[1]);
        /*
        if (restoredRowStates == null)
        {
            if (!_rowDeltaStates.isEmpty())
            {
                _rowDeltaStates.clear();
            }
        }
        else
        {
            _rowDeltaStates = (Map<String, Map<String, Object> >) restoredRowStates;
        }*/
        if (values.length > 2)
        {
            Object rs = UIComponentBase.restoreAttachedState(context, values[2]);
            if (rs == null)
            {
                if (!_rowStates.isEmpty())
                {
                    _rowStates.clear();
                }
            }
            else
            {
                _rowStates = (Map<String, Collection<Object[]> >) rs;
            }
        }
    }

    @Override
    public Object saveState(FacesContext context)
    {
        if (context.getViewRoot() != null)
        {
            if (context.getViewRoot().getAttributes().get("oam.view.resetSaveStateMode") == RESET_MODE_SOFT)
            {
                _dataModelMap.clear();
                _isValidChilds=true;
                //_rowTransientStates.clear();
            }
            if (context.getViewRoot().getAttributes().get("oam.view.resetSaveStateMode") == RESET_MODE_HARD)
            {
                _dataModelMap.clear();
                _isValidChilds=true;
                //_rowTransientStates.clear();
                _rowStates.clear();
                //_rowDeltaStates.clear();
            }
        }
        if (initialStateMarked())
        {
            Object parentSaved = super.saveState(context);
            if (context.getCurrentPhaseId() != null && 
                !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                if (parentSaved == null /*&&_rowDeltaStates.isEmpty()*/ && _rowStates.isEmpty())
                {
                    return null;
                }
                else
                {
                    Object values[] = new Object[3];
                    values[0] = super.saveState(context);
                    //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                    values[1] = null;
                    values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
                    return values;
                }
            }
            else
            {
                if (parentSaved == null /*&&_rowDeltaStates.isEmpty()*/)
                {
                    return null;
                }
                else
                {
                    Object values[] = new Object[2];
                    values[0] = super.saveState(context);
                    //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                    values[1] = null;
                    return values; 
                }
            }
        }
        else
        {
            if (context.getCurrentPhaseId() != null && 
                !PhaseId.RENDER_RESPONSE.equals(context.getCurrentPhaseId()))
            {
                Object values[] = new Object[3];
                values[0] = super.saveState(context);
                //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                values[1] = null;
                values[2] = UIComponentBase.saveAttachedState(context, _rowStates);
                return values; 
            }
            else
            {
                Object values[] = new Object[2];
                values[0] = super.saveState(context);
                //values[1] = UIComponentBase.saveAttachedState(context, _rowDeltaStates);
                values[1] = null;
                return values;
            }
        }
    }
    
    @Override
    public void encodeBegin(FacesContext context) throws IOException
    {
        _initialDescendantComponentState = null;
        if (_isValidChilds && !hasErrorMessages(context))
        {
            // Clear the data model so that when rendering code calls
            // getDataModel a fresh model is fetched from the backing
            // bean via the value-binding.
            _dataModelMap.clear();

            // When the data model is cleared it is also necessary to
            // clear the saved row state, as there is an implicit 1:1
            // relation between objects in the _rowStates and the
            // corresponding DataModel element.
            _rowStates.clear();
        }
        super.encodeBegin(context);
    }
    
    private boolean hasErrorMessages(FacesContext context)
    {
        for (Iterator<FacesMessage> iter = context.getMessages(); iter.hasNext();)
        {
            FacesMessage message = iter.next();
            if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0)
            {
                return true;
            }
        }
        return false;
    }

    @Override
    public void encodeChildren(FacesContext faces) throws IOException
    {
        if (!isRendered())
        {
            return;
        }
        
        process(faces, PhaseId.RENDER_RESPONSE);
    }

    @Override
    public boolean getRendersChildren()
    {
        if (getRendererType() != null)
        {
            Renderer renderer = getRenderer(getFacesContext());
            if (renderer != null)
            {
                return renderer.getRendersChildren();
            }
        }
        
        return true;
    }
    
    enum PropertyKeys
    {
         value
        , var
        , size
        , varStatus
        , offset
        , step
    }
}
