/*
 * 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 javax.faces.component;

import java.util.ArrayList;
import java.util.ConcurrentModificationException;
import java.util.List;
import java.util.ListIterator;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FactoryFinder;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.faces.webapp.FacesServlet;

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

/**
 * Creates a JSF View, which is a container that holds all of the components
 * that are part of the view.
 * <p>
 * Unless otherwise specified, all attributes accept static values or EL
 * expressions.
 * </p>
 * <p>
 * See the javadoc for this class in the <a
 * href="http://java.sun.com/j2ee/javaserverfaces/1.2/docs/api/index.html">JSF
 * Specification</a> for further details.
 * </p>
 */
@JSFComponent(name="f:view", bodyContent="JSP", tagClass="org.apache.myfaces.taglib.core.ViewTag")
@JSFJspProperty(name="binding", returnType="java.lang.String", tagExcluded=true)
public class UIViewRoot extends UIComponentBase
{
    public static final String COMPONENT_TYPE = "javax.faces.ViewRoot";
    public static final String COMPONENT_FAMILY = "javax.faces.ViewRoot";

    public static final String UNIQUE_ID_PREFIX = "j_id";
    private static final int ANY_PHASE_ORDINAL = PhaseId.ANY_PHASE.getOrdinal();

    private final Logger logger = Logger.getLogger(UIViewRoot.class.getName());

    /**
     * The counter which will ensure a unique component id for every component instance in the tree that
     * doesn't have an id attribute set.
     */
    private long _uniqueIdCounter = 0;

    private Locale _locale;
    private String _renderKitId;
    private String _viewId;

    // todo: is it right to save the state of _events and _phaseListeners?
    private List<FacesEvent> _events;
    private List<PhaseListener> _phaseListeners;

    private MethodExpression _beforePhaseListener;
    private MethodExpression _afterPhaseListener;

    private transient Lifecycle _lifecycle = null;

    private interface Processor
    {
        void process();
    }

    /**
     * Construct an instance of the UIViewRoot.
     */
    public UIViewRoot()
    {
        setRendererType(null);
    }

    public void queueEvent(FacesEvent event)
    {
        checkNull(event, "event");
        if (_events == null)
        {
            _events = new ArrayList<FacesEvent>();
        }
        _events.add(event);
    }

    public void processDecodes(final FacesContext context)
    {
        checkNull(context, "context");
        process(context, PhaseId.APPLY_REQUEST_VALUES, new Processor()
        {
            public void process()
            {
                UIViewRoot.super.processDecodes(context);
            }
        }, true);
    }

    public void processValidators(final FacesContext context)
    {
        checkNull(context, "context");
        process(context, PhaseId.PROCESS_VALIDATIONS, new Processor()
        {
            public void process()
            {
                UIViewRoot.super.processValidators(context);
            }
        }, true);
    }

    public void processUpdates(final FacesContext context)
    {
        checkNull(context, "context");
        process(context, PhaseId.UPDATE_MODEL_VALUES, new Processor()
        {
            public void process()
            {
                UIViewRoot.super.processUpdates(context);
            }
        }, true);
    }

    public void processApplication(final FacesContext context)
    {
        checkNull(context, "context");
        process(context, PhaseId.INVOKE_APPLICATION, null, true);
    }

    public void encodeBegin(FacesContext context) throws java.io.IOException
    {
        checkNull(context, "context");

        boolean skipPhase = false;

        try
        {
            skipPhase = notifyListeners(context, PhaseId.RENDER_RESPONSE,
                    getBeforePhaseListener(), true);
        }
        catch (Exception e)
        {
            // following the spec we have to swallow the exception
            logger.log(Level.SEVERE,
                    "Exception while processing phase listener: "
                            + e.getMessage(), e);
        }

        if (!skipPhase)
        {
            super.encodeBegin(context);
        }
    }

    public void encodeEnd(FacesContext context) throws java.io.IOException
    {
        checkNull(context, "context");
        super.encodeEnd(context);
        try
        {
            notifyListeners(context, PhaseId.RENDER_RESPONSE,
                    getAfterPhaseListener(), false);
        }
        catch (Exception e)
        {
            // following the spec we have to swallow the exception
            logger.log(Level.SEVERE,
                    "Exception while processing phase listener: "
                            + e.getMessage(), e);
        }
    }

    /**
     * Provides a unique id for this component instance.
     */
    public String createUniqueId()
    {
        StringBuilder bld = __getSharedStringBuilder();
        return bld.append(UNIQUE_ID_PREFIX).append(
                _uniqueIdCounter++).toString();
    }

    /**
     * The locale for this view.
     * <p>
     * Defaults to the default locale specified in the faces configuration file.
     * </p>
     */
    @JSFProperty
    public Locale getLocale()
    {
        if (_locale != null)
        {
            return _locale;
        }
        ValueExpression expression = getValueExpression("locale");
        if (expression != null)
        {
            return (Locale) expression.getValue(getFacesContext()
                    .getELContext());
        }
        else
        {
            Object locale = getFacesContext().getApplication().getViewHandler()
                    .calculateLocale(getFacesContext());

            if (locale instanceof Locale)
            {
                return (Locale) locale;
            }
            else if (locale instanceof String)
            {
                return stringToLocale((String) locale);
            }
        }

        return getFacesContext().getApplication().getViewHandler()
                .calculateLocale(getFacesContext());
    }

    public void setLocale(Locale locale)
    {
        this._locale = locale;
    }

    private boolean process(FacesContext context, PhaseId phaseId,
            Processor processor, boolean broadcast)
    {
        if (!notifyListeners(context, phaseId, getBeforePhaseListener(), true))
        {
            if (processor != null)
                processor.process();

            if (broadcast)
            {
                _broadcastForPhase(phaseId);
            }
        }
        if (context.getRenderResponse() || context.getResponseComplete())
        {
            clearEvents();
        }
        return notifyListeners(context, phaseId, getAfterPhaseListener(), false);
    }

    /**
     * Invoke view-specific phase listeners, plus an optional EL MethodExpression.
     * <p>
     * JSF1.2 adds the ability for PhaseListener objects to be added to a UIViewRoot instance,
     * and for "beforePhaseListener" and "afterPhaseListener" EL expressions to be defined
     * on the viewroot. This method is expected to be called at appropriate times, and will
     * then execute the relevant listener callbacks.
     * <p>
     * Parameter "listener" may be null. If not null, then it is an EL expression pointing
     * to a user method that will be invoked.
     * <p>
     * Note that the global PhaseListeners are invoked via the Lifecycle implementation, not
     * from this method here.
     */
    private boolean notifyListeners(FacesContext context, PhaseId phaseId,
            MethodExpression listener, boolean beforePhase)
    {
        boolean skipPhase = false;

        if (listener != null
                || (_phaseListeners != null && !_phaseListeners.isEmpty()))
        {
            PhaseEvent event = createEvent(context, phaseId);

            if (listener != null)
            {
                listener.invoke(context.getELContext(), new Object[]
                { event });
                skipPhase = context.getResponseComplete()
                        || context.getRenderResponse();
            }

            if (_phaseListeners != null && !_phaseListeners.isEmpty())
            {
                for (PhaseListener phaseListener : _phaseListeners)
                {
                    PhaseId listenerPhaseId = phaseListener.getPhaseId();
                    if (phaseId.equals(listenerPhaseId)
                            || PhaseId.ANY_PHASE.equals(listenerPhaseId))
                    {
                        if (beforePhase)
                        {
                            phaseListener.beforePhase(event);
                        }
                        else
                        {
                            phaseListener.afterPhase(event);
                        }
                        skipPhase = context.getResponseComplete()
                                || context.getRenderResponse();
                    }
                }
            }
        }

        return skipPhase;
    }

    private PhaseEvent createEvent(FacesContext context, PhaseId phaseId)
    {
        if (_lifecycle == null)
        {
            LifecycleFactory factory = (LifecycleFactory) FactoryFinder
                    .getFactory(FactoryFinder.LIFECYCLE_FACTORY);
            String id = context.getExternalContext().getInitParameter(
                    FacesServlet.LIFECYCLE_ID_ATTR);
            if (id == null)
            {
                id = LifecycleFactory.DEFAULT_LIFECYCLE;
            }
            _lifecycle = factory.getLifecycle(id);
        }
        return new PhaseEvent(context, phaseId, _lifecycle);
    }

    private void _broadcastForPhase(PhaseId phaseId)
    {
        if (_events == null)
        {
            return;
        }

        boolean abort = false;

        int phaseIdOrdinal = phaseId.getOrdinal();
        for (ListIterator<FacesEvent> listiterator = _events.listIterator(); listiterator
                .hasNext();)
        {
            FacesEvent event = listiterator.next();
            int ordinal = event.getPhaseId().getOrdinal();
            if (ordinal == ANY_PHASE_ORDINAL || ordinal == phaseIdOrdinal)
            {
                UIComponent source = event.getComponent();
                try
                {
                    source.broadcast(event);
                }
                catch (AbortProcessingException e)
                {
                    // abort event processing
                    // Page 3-30 of JSF 1.1 spec: "Throw an
                    // AbortProcessingException, to tell the JSF implementation
                    // that no further broadcast of this event, or any further
                    // events, should take place."
                    abort = true;
                    break;
                }
                finally
                {
                    try
                    {
                        listiterator.remove();
                    }
                    catch (ConcurrentModificationException cme)
                    {
                        int eventIndex = listiterator.previousIndex();
                        _events.remove(eventIndex);
                        listiterator = _events.listIterator();
                    }
                }
            }
        }

        if (abort)
        {
            // TODO: abort processing of any event of any phase or just of any
            // event of the current phase???
            clearEvents();
        }
    }

    private void clearEvents()
    {
        _events = null;
    }

    private void checkNull(Object value, String valueLabel)
    {
        if (value == null)
        {
            throw new NullPointerException(valueLabel + " is null");
        }
    }

    private Locale stringToLocale(String localeStr)
    {
        // locale expr: \[a-z]{2}((-|_)[A-Z]{2})?

        if (localeStr.contains("_") || localeStr.contains("-"))
        {
            if (localeStr.length() == 2)
            {
                // localeStr is the lang
                return new Locale(localeStr);
            }
        }
        else
        {
            if (localeStr.length() == 5)
            {
                String lang = localeStr.substring(0, 1);
                String country = localeStr.substring(3, 4);
                return new Locale(lang, country);
            }
        }

        return Locale.getDefault();
    }

    /**
     * Defines what renderkit should be used to render this view.
     */
    @JSFProperty
    public String getRenderKitId()
    {
        if (_renderKitId != null)
        {
            return _renderKitId;
        }
        ValueExpression expression = getValueExpression("renderKitId");
        if (expression != null)
        {
            return (String) expression.getValue(getFacesContext()
                    .getELContext());
        }
        return null;
    }

    public void setRenderKitId(String renderKitId)
    {
        this._renderKitId = renderKitId;
    }

    /**
     * DO NOT USE.
     * <p>
     * This inherited property is disabled. Although this class extends a base-class that
     * defines a read/write rendered property, this particular subclass does not
     * support setting it. Yes, this is broken OO design: direct all complaints
     * to the JSF spec group.
     */
    @Override
    @JSFProperty(tagExcluded=true)
    public void setRendered(boolean state)
    {
        //Call parent method due to TCK problems
        super.setRendered(state);
        //throw new UnsupportedOperationException();
    }

    @Override
    public boolean isRendered()
    {
        //Call parent method due to TCK problems
        return super.isRendered();
    }

    /**
     * DO NOT USE.
     * <p>
     * Although this class extends a base-class that defines a read/write id
     * property, it makes no sense for this particular subclass to support it.
     * The tag library does not export this property for use, but there is no
     * way to "undeclare" a java method. Yes, this is broken OO design: direct
     * all complaints to the JSF spec group.
     * <p>
     * This property should be disabled (ie throw an exception if invoked).
     * However there are currently several places that call this method (eg
     * during restoreState) so it just does the normal thing for the moment.
     * TODO: fix callers then make this throw an exception.
     * 
     * @JSFProperty tagExcluded="true"
     */
    public void setId(String id)
    {
        // throw new UnsupportedOperationException();

        // Leave enabled for now. Things like the TreeStructureManager call this,
        // even though they probably should not.
        super.setId(id);
    }

    public String getId()
    {
        // Should just return null. But as setId passes the method on, do same here.
        return super.getId();
    }

    /**
     * DO NOT USE.
     * <p>
     * As this component has no "id" property, it has no clientId property either.
     */
    public String getClientId(FacesContext context)
    {
        return super.getClientId(context);
        //Call parent method due to TCK problems
        //return null;
    }

    /**
     * A unique identifier for the "template" from which this view was generated.
     * <p>
     * Typically this is the filesystem path to the template file, but the exact
     * details are the responsibility of the current ViewHandler implementation.
     */
    @JSFProperty(tagExcluded = true)
    public String getViewId()
    {
        return _viewId;
    }

    public void setViewId(String viewId)
    {
        // It really doesn't make much sense to allow null here.
        // However the TCK does not check for it, and sun's implementation
        // allows it so here we allow it too.
        this._viewId = viewId;
    }

    /**
     * Adds a The phaseListeners attached to ViewRoot.
     */
    public void addPhaseListener(PhaseListener phaseListener)
    {
        if (phaseListener == null)
            throw new NullPointerException("phaseListener");
        if (_phaseListeners == null)
            _phaseListeners = new ArrayList<PhaseListener>();

        _phaseListeners.add(phaseListener);
    }

    /**
     * Removes a The phaseListeners attached to ViewRoot.
     */
    public void removePhaseListener(PhaseListener phaseListener)
    {
        if (phaseListener == null || _phaseListeners == null)
            return;

        _phaseListeners.remove(phaseListener);
    }

    /**
     * MethodBinding pointing to a method that takes a
     * javax.faces.event.PhaseEvent and returns void,
     * called before every phase except for restore view.
     * 
     * @return the new beforePhaseListener value
     */
    @JSFProperty(stateHolder = true, returnSignature = "void", methodSignature = "javax.faces.event.PhaseEvent", jspName = "beforePhase")
    public MethodExpression getBeforePhaseListener()
    {
        if (_beforePhaseListener != null)
        {
            return _beforePhaseListener;
        }
        ValueExpression expression = getValueExpression("beforePhaseListener");
        if (expression != null)
        {
            return (MethodExpression) expression.getValue(getFacesContext()
                    .getELContext());
        }
        return null;
    }

    /**
     * Sets
     * 
     * @param beforePhaseListener
     *            the new beforePhaseListener value
     */
    public void setBeforePhaseListener(MethodExpression beforePhaseListener)
    {
        this._beforePhaseListener = beforePhaseListener;
    }

    /**
     * MethodBinding pointing to a method that takes a
     * javax.faces.event.PhaseEvent and returns void,
     * called after every phase except for restore view.
     * 
     * @return the new afterPhaseListener value
     */
    @JSFProperty(stateHolder = true, returnSignature = "void", methodSignature = "javax.faces.event.PhaseEvent", jspName = "afterPhase")
    public MethodExpression getAfterPhaseListener()
    {
        if (_afterPhaseListener != null)
        {
            return _afterPhaseListener;
        }
        ValueExpression expression = getValueExpression("afterPhaseListener");
        if (expression != null)
        {
            return (MethodExpression) expression.getValue(getFacesContext()
                    .getELContext());
        }
        return null;
    }

    /**
     * Sets
     * 
     * @param afterPhaseListener
     *            the new afterPhaseListener value
     */
    public void setAfterPhaseListener(MethodExpression afterPhaseListener)
    {
        this._afterPhaseListener = afterPhaseListener;
    }

    @Override
    public Object saveState(FacesContext facesContext)
    {
        Object[] values = new Object[8];
        values[0] = super.saveState(facesContext);
        values[1] = _locale;
        values[2] = _renderKitId;
        values[3] = _viewId;
        values[4] = _uniqueIdCounter;
        values[5] = saveAttachedState(facesContext, _phaseListeners);
        values[6] = saveAttachedState(facesContext, _beforePhaseListener);
        values[7] = saveAttachedState(facesContext, _afterPhaseListener);

        return values;
    }

    @Override
    public void restoreState(FacesContext facesContext, Object state)
    {
        Object[] values = (Object[]) state;
        super.restoreState(facesContext, values[0]);
        _locale = (Locale) values[1];
        _renderKitId = (String) values[2];
        _viewId = (String) values[3];
        _uniqueIdCounter = (Long) values[4];
        _phaseListeners = (List) restoreAttachedState(facesContext, values[5]);
        _beforePhaseListener = (MethodExpression) restoreAttachedState(
                facesContext, values[6]);
        _afterPhaseListener = (MethodExpression) restoreAttachedState(
                facesContext, values[7]);
    }

    @Override
    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }
}
