/*
 * 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.test.mock.visit;

import java.util.AbstractCollection;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
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;

/**
 * <p>A VisitContext implementation that is
 * used when performing a partial component tree visit.</p>
 * 
 * @author Werner Punz, Blake Sullivan (latest modification by $Author: lu4242 $)
 * @version $Rev: 949094 $ $Date: 2010-05-27 22:59:10 -0500 (Jue, 27 May 2010) $
 * @since 1.0.0
 */
public class PartialVisitContext extends VisitContext
{

    /**
     * Creates a PartialVisitorContext instance.
     * @param facesContext the FacesContext for the current request
     * @param clientIds the client ids of the components to visit
     * @throws NullPointerException  if {@code facesContext}
     *                               is {@code null}
     */
    public PartialVisitContext(FacesContext facesContext,
            Collection<String> clientIds)
    {
        this(facesContext, clientIds, null);
    }

    /**
     * Creates a PartialVisitorContext instance with the specified hints.
     * @param facesContext the FacesContext for the current request
     * @param clientIds the client ids of the components to visit
     * @param hints a the VisitHints for this visit
     * @throws NullPointerException  if {@code facesContext}
     *                               is {@code null}
     * @throws IllegalArgumentException if the phaseId is specified and
     * hints does not contain VisitHint.EXECUTE_LIFECYCLE
     */
    public PartialVisitContext(FacesContext facesContext,
            Collection<String> clientIds, Set<VisitHint> hints)
    {
        if (facesContext == null)
            throw new NullPointerException();

        _facesContext = facesContext;

        // Copy the client ids into a HashSet to allow for quick lookups.
        Set<String> clientIdSet = (clientIds == null) ? new HashSet<String>()
                : new HashSet<String>(clientIds);

        // Initialize our various collections
        // We maintain 4 collections:
        //
        // 1. clientIds: contains all of the client ids to visit
        // 2. ids: contains just ids (not client ids) to visit.
        //    We use this to optimize our check to see whether a
        //    particular component is in the visit set (ie. to
        //    avoid having to compute the client id).
        // 3. subtreeClientIds: contains client ids to visit broken
        //    out by naming container subtree.  (Needed by
        //    getSubtreeIdsToVisit()).
        // 4. unvisitedClientIds: contains the client ids to visit that
        //    have not yet been visited.
        //
        // We populate these now.
        //
        // Note that we use default HashSet/Map initial capacities, though
        // perhaps we could pick more intelligent defaults.

        // Initialize unvisitedClientIds collection
        _unvisitedClientIds = new HashSet<String>();

        // Initialize ids collection
        _ids = new HashSet<String>();

        // Intialize subtreeClientIds collection
        _subtreeClientIds = new HashMap<String, Collection<String>>();

        // Initialize the clientIds collection.  Note that we proxy 
        // this collection so that we can trap adds/removes and sync 
        // up all of the other collections.
        _clientIds = new CollectionProxy<String>(new HashSet<String>());

        // Finally, populate the clientIds collection.  This has the
        // side effect of populating all of the other collections.       
        _clientIds.addAll(clientIdSet);

        // Copy and store hints - ensure unmodifiable and non-empty
        EnumSet<VisitHint> hintsEnumSet = ((hints == null) || (hints.isEmpty())) ? EnumSet
                .noneOf(VisitHint.class)
                : EnumSet.copyOf(hints);

        _hints = Collections.unmodifiableSet(hintsEnumSet);
    }

    /**
     * @see VisitContext#getFacesContext VisitContext.getFacesContext()
     */
    @Override
    public FacesContext getFacesContext()
    {
        return _facesContext;
    }

    /**
     * @see VisitContext#getHints VisitContext.getHints
     */
    @Override
    public Set<VisitHint> getHints()
    {
        return _hints;
    }

    /**
     * @see VisitContext#getIdsToVisit VisitContext.getIdsToVisit()
     */
    @Override
    public Collection<String> getIdsToVisit()
    {
        // We just return our clientIds collection.  This is
        // the modifiable (but proxied) collection of all of
        // the client ids to visit.
        return _clientIds;
    }

    /**
     * @see VisitContext#getSubtreeIdsToVisit VisitContext.getSubtreeIdsToVisit()
     */
    @Override
    public Collection<String> getSubtreeIdsToVisit(UIComponent component)
    {
        // Make sure component is a NamingContainer
        if (!(component instanceof NamingContainer))
        {
            throw new IllegalArgumentException(
                    "Component is not a NamingContainer: " + component);
        }

        String clientId = component.getClientId(getFacesContext());
        Collection<String> ids = _subtreeClientIds.get(clientId);

        if (ids == null)
            return Collections.emptyList();
        else
            return Collections.unmodifiableCollection(ids);
    }

    /**
     * @see VisitContext#invokeVisitCallback VisitContext.invokeVisitCallback()
     */
    @Override
    public VisitResult invokeVisitCallback(UIComponent component,
            VisitCallback callback)
    {
        // First sure that we should visit this component - ie.
        // that this component is represented in our id set.
        String clientId = _getVisitId(component);

        if (clientId == null)
        {
            // Not visiting this component, but allow visit to
            // continue into this subtree in case we've got
            // visit targets there.
            return VisitResult.ACCEPT;
        }

        // If we made it this far, the component matches one of
        // client ids, so perform the visit.
        VisitResult result = callback.visit(this, component);

        // Remove the component from our "unvisited" collection
        _unvisitedClientIds.remove(clientId);

        // If the unvisited collection is now empty, we are done.
        // Return VisitResult.COMPLETE to terminate the visit.
        if (_unvisitedClientIds.isEmpty())
            return VisitResult.COMPLETE;
        else
        {
            // Otherwise, just return the callback's result 
            return result;
        }
    }

    // Called by CollectionProxy to notify PartialVisitContext that
    // an new id has been added.
    private void _idAdded(String clientId)
    {
        // An id to visit has been added, update our other
        // collections to reflect this.

        // Update the ids collection
        _ids.add(_getIdFromClientId(clientId));

        // Update the unvisited ids collection
        _unvisitedClientIds.add(clientId);

        // Update the subtree ids collection
        _addSubtreeClientId(clientId);
    }

    // Called by CollectionProxy to notify PartialVisitContext that
    // an id has been removed
    private void _idRemoved(String clientId)
    {
        // An id to visit has been removed, update our other
        // collections to reflect this.  Note that we don't
        // update the ids collection, since we ids (non-client ids)
        // may not be unique.

        // Update the unvisited ids collection
        _unvisitedClientIds.remove(clientId);

        // Update the subtree ids collection
        _removeSubtreeClientId(clientId);
    }

    // Tests whether the specified component should be visited.
    // If so, returns its client id.  If not, returns null.
    private String _getVisitId(UIComponent component)
    {
        // We first check to see whether the component's id
        // is in our id collection.  We do this before checking
        // for the full client id because getting the full client id
        // is more expensive than just getting the local id.
        String id = component.getId();

        if ((id != null) && !_ids.contains(id))
            return null;

        // The id was a match - now check the client id.
        // note that client id should never be null (should be
        // generated even if id is null, so asserting this.)
        String clientId = component.getClientId(getFacesContext());
        assert (clientId != null);

        return _clientIds.contains(clientId) ? clientId : null;
    }

    // Converts an client id into a plain old id by ripping
    // out the trailing id segmetn.
    private String _getIdFromClientId(String clientId)
    {
        final char separator = UINamingContainer
                .getSeparatorChar(_facesContext);
        int lastIndex = clientId.lastIndexOf(separator);

        String id = null;

        if (lastIndex < 0)
        {
            id = clientId;
        }
        else if (lastIndex < (clientId.length() - 1))
        {
            id = clientId.substring(lastIndex + 1);
        }
        else
        {
            // TODO log warning for trailing colon case
        }

        return id;
    }

    // Given a single client id, populate the subtree map with all possible
    // subtree client ids
    private void _addSubtreeClientId(String clientId)
    {
        // Loop over the client id and find the substring corresponding to
        // each ancestor NamingContainer client id.  For each ancestor
        // NamingContainer, add an entry into the map for the full client
        // id.
        final char separator = UINamingContainer
                .getSeparatorChar(_facesContext);

        int length = clientId.length();

        for (int i = 0; i < length; i++)
        {
            if (clientId.charAt(i) == separator)
            {
                // We found an ancestor NamingContainer client id - add 
                // an entry to the map.
                String namingContainerClientId = clientId.substring(0, i);

                // Check to see whether we've already ids under this
                // NamingContainer client id.  If not, create the 
                // Collection for this NamingContainer client id and
                // stash it away in our map
                Collection<String> c = _subtreeClientIds
                        .get(namingContainerClientId);

                if (c == null)
                {
                    // TODO: smarter initial size?
                    c = new ArrayList<String>();
                    _subtreeClientIds.put(namingContainerClientId, c);
                }

                // Stash away the client id
                c.add(clientId);
            }
        }
    }

    // Given a single client id, remove any entries corresponding
    // entries from our subtree collections
    private void _removeSubtreeClientId(String clientId)
    {
        // Loop through each entry in the map and check to see whether
        // the client id to remove should be contained in the corresponding
        // collection - ie. whether the key (the NamingContainer client id)
        // is present at the start of the client id to remove.
        for (String key : _subtreeClientIds.keySet())
        {
            if (clientId.startsWith(key))
            {
                // If the clientId starts with the key, we should
                // have an entry for this clientId in the corresponding
                // collection.  Remove it.
                Collection<String> ids = _subtreeClientIds.get(key);
                ids.remove(clientId);
            }
        }
    }

    // Little proxy collection implementation.  We proxy the id
    // collection so that we can detect modifications and update
    // our internal state when ids to visit are added or removed.
    private class CollectionProxy<E extends String> extends
            AbstractCollection<E>
    {
        private CollectionProxy(Collection<E> wrapped)
        {
            _wrapped = wrapped;
        }

        @Override
        public int size()
        {
            return _wrapped.size();
        }

        @Override
        public Iterator<E> iterator()
        {
            return new IteratorProxy<E>(_wrapped.iterator());
        }

        @Override
        public boolean add(E o)
        {
            boolean added = _wrapped.add(o);

            if (added)
            {
                _idAdded(o);
            }

            return added;
        }

        private final Collection<E> _wrapped;
    }

    // Little proxy iterator implementation used by CollectionProxy
    // so that we can catch removes.
    private class IteratorProxy<E extends String> implements Iterator<E>
    {
        private IteratorProxy(Iterator<E> wrapped)
        {
            _wrapped = wrapped;
        }

        public boolean hasNext()
        {
            return _wrapped.hasNext();
        }

        public E next()
        {
            _current = _wrapped.next();

            return _current;
        }

        public void remove()
        {
            if (_current != null)
            {
                _idRemoved(_current);
            }

            _wrapped.remove();
        }

        private final Iterator<E> _wrapped;

        private E _current = null;
    }

    // The client ids to visit
    private final Collection<String> _clientIds;

    // The ids to visit
    private final Collection<String> _ids;

    // The client ids that have yet to be visited
    private final Collection<String> _unvisitedClientIds;

    // This map contains the information needed by getIdsToVisit().
    // The keys in this map are NamingContainer client ids.  The values
    // are collections containing all of the client ids to visit within
    // corresponding naming container.
    private final Map<String, Collection<String>> _subtreeClientIds;

    // The FacesContext for this request
    private final FacesContext _facesContext;

    // Our visit hints
    private final Set<VisitHint> _hints;
}