/*
 * 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.lifecycle;

import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.faces.FacesException;
import javax.faces.FactoryFinder;
import javax.faces.application.ProjectStage;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.ClientWindow;
import javax.faces.lifecycle.ClientWindowFactory;
import javax.faces.lifecycle.Lifecycle;

import org.apache.myfaces.config.FacesConfigurator;
import org.apache.myfaces.util.lang.Assert;
import org.apache.myfaces.util.DebugUtils;

/**
 * Implements the lifecycle as described in Spec. 1.0 PFD Chapter 2
 * 
 * @author Manfred Geiler (latest modification by $Author$)
 * @author Nikolay Petrov
 * @version $Revision$ $Date$
 */
public class LifecycleImpl extends Lifecycle
{
    private static final Logger log = Logger.getLogger(LifecycleImpl.class.getName());
    
    /**
     * Boolean.TRUE is stored under this key in the application map if
     * the first request has been processed.
     */
    public static final String FIRST_REQUEST_PROCESSED_PARAM = "org.apache.myfaces.lifecycle.first.request.processed";
    
    private final PhaseExecutor[] lifecycleExecutors;
    private final PhaseExecutor renderExecutor;
    private final ClientWindowFactory clientWindowFactory;
    private final List<PhaseListener> phaseListeners;

    /**
     * This variable should be marked as volatile to ensure all threads can see it
     * after the first request is processed. Note that LifecycleImpl instance could be
     * shared by multiple requests at the same time, so this is relevant to prevent
     * multiple updates to FIRST_REQUEST_PROCESSED_PARAM. Really since the value
     * only changes from false to true, have a racy single check here does not harm, but
     * note in this case the semantic of the variable must be preserved.
     */
    private volatile boolean _firstRequestProcessed = false;
    
    public LifecycleImpl()
    {
        // hide from public access
        lifecycleExecutors = new PhaseExecutor[] { new RestoreViewExecutor(), new ApplyRequestValuesExecutor(),
                new ProcessValidationsExecutor(), new UpdateModelValuesExecutor(), new InvokeApplicationExecutor() };

        renderExecutor = new RenderResponseExecutor();
        clientWindowFactory = (ClientWindowFactory) FactoryFinder.getFactory(FactoryFinder.CLIENT_WINDOW_FACTORY);
        phaseListeners = new CopyOnWriteArrayList<>();
    }
    
    @Override
    public void attachWindow(FacesContext facesContext)
    {
        ClientWindow clientWindow = facesContext.getExternalContext().getClientWindow();
        if (clientWindow == null)
        {
            clientWindow = getClientWindowFactory().getClientWindow(facesContext);
        }
        if (clientWindow != null)
        {
            clientWindow.decode(facesContext);
            facesContext.getExternalContext().setClientWindow(clientWindow);
        }
    }
    
    protected ClientWindowFactory getClientWindowFactory()
    {
        return clientWindowFactory;
    }

    @Override
    public void execute(FacesContext facesContext) throws FacesException
    {
        if (!facesContext.isProjectStage(ProjectStage.Production))
        {
            new FacesConfigurator(facesContext.getExternalContext()).update();
        }

        PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
        for (PhaseExecutor executor : lifecycleExecutors)
        {
            if (executePhase(facesContext, executor, phaseListenerMgr))
            {
                return;
            }
        }
    }

    private boolean executePhase(FacesContext context, PhaseExecutor executor, PhaseListenerManager phaseListenerMgr)
        throws FacesException
    {
        boolean skipFurtherProcessing = false;

        if (log.isLoggable(Level.FINEST))
        {
            log.finest("entering " + executor.getPhase() + " in " + LifecycleImpl.class.getName());
        }

        PhaseId currentPhaseId = executor.getPhase();
        Flash flash = context.getExternalContext().getFlash();

        try
        {
            /* 
             * Specification, section 2.2
             * The default request lifecycle processing implementation must ensure that the currentPhaseId property 
             * of the FacesContext instance for this request is set with the proper PhaseId constant for the current 
             * phase as the first instruction at the beginning of each phase
             */
            context.setCurrentPhaseId(currentPhaseId);
            
            flash.doPrePhaseActions(context);
            
            // let the PhaseExecutor do some pre-phase actions
            executor.doPrePhaseActions(context);

            phaseListenerMgr.informPhaseListenersBefore(currentPhaseId);

            if (isResponseComplete(context, currentPhaseId, true))
            {
                // have to return right away
                return true;
            }
            if (shouldRenderResponse(context, currentPhaseId, true))
            {
                skipFurtherProcessing = true;
            }

            if (executor.execute(context))
            {
                return true;
            }
        }
        
        catch (Throwable e)
        {
            // JSF 2.0: publish the executor's exception (if any).
            
            publishException (e, currentPhaseId, context);
        }
        
        finally
        {
            phaseListenerMgr.informPhaseListenersAfter(currentPhaseId);
            
            flash.doPostPhaseActions(context);
            
        }
        
        context.getExceptionHandler().handle();
        
        if (isResponseComplete(context, currentPhaseId, false) || shouldRenderResponse(context, currentPhaseId, false))
        {
            // since this phase is completed we don't need to return right away even if the response is completed
            skipFurtherProcessing = true;
        }

        if (!skipFurtherProcessing && log.isLoggable(Level.FINEST))
        {
            log.finest("exiting " + executor.getPhase() + " in " + LifecycleImpl.class.getName());
        }

        return skipFurtherProcessing;
    }

    @Override
    public void render(FacesContext facesContext) throws FacesException
    {
        // if the response is complete we should not be invoking the phase listeners
        if (isResponseComplete(facesContext, renderExecutor.getPhase(), true))
        {
            return;
        }
        if (log.isLoggable(Level.FINEST))
        {
            log.finest("entering " + renderExecutor.getPhase() + " in " + LifecycleImpl.class.getName());
        }

        PhaseListenerManager phaseListenerMgr = new PhaseListenerManager(this, facesContext, getPhaseListeners());
        Flash flash = facesContext.getExternalContext().getFlash();

        try
        {
            facesContext.setCurrentPhaseId(renderExecutor.getPhase());

            flash.doPrePhaseActions(facesContext);

            // let the PhaseExecutor do some pre-phase actions
            renderExecutor.doPrePhaseActions(facesContext);

            phaseListenerMgr.informPhaseListenersBefore(renderExecutor.getPhase());
            // also possible that one of the listeners completed the response
            if (isResponseComplete(facesContext, renderExecutor.getPhase(), true))
            {
                return;
            }

            renderExecutor.execute(facesContext);
        }

        catch (Throwable e)
        {
            // JSF 2.0: publish the executor's exception (if any).

            publishException (e, renderExecutor.getPhase(), facesContext);
        }

        finally
        {
            phaseListenerMgr.informPhaseListenersAfter(renderExecutor.getPhase());
            flash.doPostPhaseActions(facesContext);

            // publish a field in the application map to indicate
            // that the first request has been processed
            requestProcessed(facesContext);
        }

        facesContext.getExceptionHandler().handle();

        if (log.isLoggable(Level.FINEST))
        {
            // Note: DebugUtils Logger must also be in trace level
            DebugUtils.traceView("View after rendering");
        }

        if (log.isLoggable(Level.FINEST))
        {
            log.finest("exiting " + renderExecutor.getPhase() + " in " + LifecycleImpl.class.getName());
        }
    }

    private boolean isResponseComplete(FacesContext facesContext, PhaseId phase, boolean before)
    {
        boolean flag = false;
        if (facesContext.getResponseComplete())
        {
            if (log.isLoggable(Level.FINE))
            {
                log.fine("exiting from lifecycle.execute in " + phase
                        + " because getResponseComplete is true from one of the " + (before ? "before" : "after")
                        + " listeners");
            }
            flag = true;
        }
        return flag;
    }

    private boolean shouldRenderResponse(FacesContext facesContext, PhaseId phase, boolean before)
    {
        boolean flag = false;
        if (facesContext.getRenderResponse())
        {
            if (log.isLoggable(Level.FINE))
            {
                log.fine("exiting from lifecycle.execute in " + phase
                        + " because getRenderResponse is true from one of the " + (before ? "before" : "after")
                        + " listeners");
            }
            flag = true;
        }
        return flag;
    }

    @Override
    public void addPhaseListener(PhaseListener phaseListener)
    {
        Assert.notNull(phaseListener, "phaseListener");

        phaseListeners.add(phaseListener);
    }

    @Override
    public void removePhaseListener(PhaseListener phaseListener)
    {
        Assert.notNull(phaseListener, "phaseListener");

        phaseListeners.remove(phaseListener);
    }

    @Override
    public PhaseListener[] getPhaseListeners()
    {
        return phaseListeners.toArray(new PhaseListener[phaseListeners.size()]);
    }
    
    private void publishException(Throwable e, PhaseId phaseId, FacesContext facesContext)
    {
        ExceptionQueuedEventContext context = new ExceptionQueuedEventContext (facesContext, e, null, phaseId);
        
        facesContext.getApplication().publishEvent (facesContext, ExceptionQueuedEvent.class, context);
    }
    
    /**
     * This method places an attribute on the application map to 
     * indicate that the first request has been processed. This
     * attribute is used by several methods in ApplicationImpl 
     * to determine whether or not to throw an IllegalStateException
     * @param facesContext
     */
    private void requestProcessed(FacesContext facesContext)
    {
        if (!_firstRequestProcessed)
        {
            // The order here is important. First it is necessary to put
            // the value on application map before change the value here.
            // If multiple threads reach this point concurrently, the
            // variable will be written on the application map at the same
            // time but always with the same value.
            facesContext.getExternalContext().getApplicationMap()
                .put(FIRST_REQUEST_PROCESSED_PARAM, Boolean.TRUE);
            
            _firstRequestProcessed = true;
        }        
    }
}
