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

import javax.faces.application.FacesMessage;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.Flash;
import javax.faces.event.PhaseId;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.io.Serializable;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;

/**
 * <p>Mock implementation of <code>Flash</code>.</p>
 * <p/>
 * $Id$
 *
 * @since 1.0.0
 */
public class MockFlash extends Flash
{

    /**
     * Key on app map to keep current instance
     */
    static protected final String FLASH_INSTANCE = MockFlash.class.getName()
            + ".INSTANCE";

    /**
     * Key used to check if there is the current request will be or was redirected
     */
    static protected final String FLASH_REDIRECT = MockFlash.class.getName()
            + ".REDIRECT";

    /**
     * Key used to check if this request should keep messages (like tomahawk sandbox RedirectTracker.
     * Used when post-redirect-get pattern is used)
     */
    static protected final String FLASH_KEEP_MESSAGES = MockFlash.class
            .getName()
            + ".KEEP_MESSAGES";

    static protected final String FLASH_KEEP_MESSAGES_LIST = "KEEPMESSAGESLIST";

    /**
     * Session map prefix to flash maps
     */
    static protected final String FLASH_SCOPE_CACHE = MockFlash.class.getName()
            + ".SCOPE";

    static protected final String FLASH_CURRENT_MAP_CACHE = MockFlash.class
            .getName()
            + ".CURRENTMAP.CACHE";

    static protected final String FLASH_CURRENT_MAP_KEY = MockFlash.class
            .getName()
            + ".CURRENTMAP.KEY";

    static protected final String FLASH_POSTBACK_MAP_CACHE = MockFlash.class
            .getName()
            + ".POSTBACKMAP.CACHE";

    static protected final String FLASH_POSTBACK_MAP_KEY = MockFlash.class
            .getName()
            + ".POSTBACKMAP.KEY";

    static private final char SEPARATOR_CHAR = '.';

    // the current token value
    private final AtomicLong _count;

    public MockFlash()
    {
        _count = new AtomicLong(_getSeed());
    }

    /**
     * @return a cryptographically secure random number to use as the _count seed
     */
    private static long _getSeed()
    {
        SecureRandom rng;
        try
        {
            // try SHA1 first
            rng = SecureRandom.getInstance("SHA1PRNG");
        }
        catch (NoSuchAlgorithmException e)
        {
            // SHA1 not present, so try the default (which could potentially not be
            // cryptographically secure)
            rng = new SecureRandom();
        }

        // use 48 bits for strength and fill them in
        byte[] randomBytes = new byte[6];
        rng.nextBytes(randomBytes);

        // convert to a long
        return new BigInteger(randomBytes).longValue();
    }

    /**
     * @return the next token to be assigned to this request
     */
    protected String _getNextToken()
    {
        // atomically increment the value
        long nextToken = _count.incrementAndGet();

        // convert using base 36 because it is a fast efficient subset of base-64
        return Long.toString(nextToken, 36);
    }

    /**
     * Return a Flash instance from the application map
     *
     * @param context
     * @return
     */
    public static Flash getCurrentInstance(ExternalContext context)
    {
        Map<String, Object> applicationMap = context.getApplicationMap();
        Flash flash = (Flash) applicationMap.get(FLASH_INSTANCE);

        synchronized (applicationMap)
        {
            if (flash == null)
            {
                flash = new MockFlash();
                context.getApplicationMap().put(FLASH_INSTANCE, flash);
            }
        }
        return flash;
    }

    /**
     * Return a wrapper from the session map used to implement flash maps
     * for more information see SubKeyMap doc
     */
    @SuppressWarnings("unchecked")
    private Map<String, Object> _getMapFromSession(FacesContext context,
            String token, boolean createIfNeeded)
    {
        ExternalContext external = context.getExternalContext();
        Object session = external.getSession(true);

        Map<String, Object> map = null;

        // Synchronize on the session object to ensure that
        // we don't ever create two different caches
        synchronized (session)
        {
            map = (Map<String, Object>) external.getSessionMap().get(token);
            if ((map == null) && createIfNeeded)
            {
                map = new MockSubKeyMap<Object>(context.getExternalContext()
                        .getSessionMap(), token);
            }
        }

        return map;
    }

    /**
     * Return the flash map created on this traversal. This one will be sent
     * on next request, so it will be retrieved as postback map of the next
     * request.
     * <p/>
     * Note it is supposed that FLASH_CURRENT_MAP_KEY is initialized before
     * restore view phase (see doPrePhaseActions() for details).
     *
     * @param context
     * @return
     */
    @SuppressWarnings("unchecked")
    protected Map<String, Object> getCurrentRequestMap(FacesContext context)
    {
        Map<String, Object> requestMap = context.getExternalContext()
                .getRequestMap();
        Map<String, Object> map = (Map<String, Object>) requestMap
                .get(FLASH_CURRENT_MAP_CACHE);
        if (map == null)
        {
            String token = (String) requestMap.get(FLASH_CURRENT_MAP_KEY);
            String fullToken = FLASH_SCOPE_CACHE + SEPARATOR_CHAR + token;
            map = _getMapFromSession(context, fullToken, true);
            requestMap.put(FLASH_CURRENT_MAP_CACHE, map);
        }
        return map;
    }

    @SuppressWarnings("unchecked")
    protected Map<String, Object> getPostbackRequestMap(FacesContext context)
    {
        Map<String, Object> requestMap = context.getExternalContext()
                .getRequestMap();
        Map<String, Object> map = (Map<String, Object>) requestMap
                .get(FLASH_POSTBACK_MAP_CACHE);
        if (map == null)
        {
            String token = (String) requestMap.get(FLASH_POSTBACK_MAP_KEY);
            if (token == null && isRedirect())
            {
                // In post-redirect-get, request values are reset, so we need
                // to get the postback key again.
                token = _getPostbackMapKey(context.getExternalContext());
            }
            String fullToken = FLASH_SCOPE_CACHE + SEPARATOR_CHAR + token;
            map = _getMapFromSession(context, fullToken, true);
            requestMap.put(FLASH_POSTBACK_MAP_CACHE, map);
        }
        return map;
    }

    /**
     * Get the proper map according to the current phase:
     * <p/>
     * Normal case:
     * <p/>
     * - First request, restore view phase (create a new one): current map n
     * - First request, execute phase: Skipped
     * - First request, render  phase: current map n
     * <p/>
     * Current map n saved and put as postback map n
     * <p/>
     * - Second request, execute phase: postback map n
     * - Second request, render  phase: current map n+1
     * <p/>
     * Post Redirect Get case: Redirect is triggered by a call to setRedirect(true) from NavigationHandler
     * or earlier using c:set tag.
     * <p/>
     * - First request, restore view phase (create a new one): current map n
     * - First request, execute phase: Skipped
     * - First request, render  phase: current map n
     * <p/>
     * Current map n saved and put as postback map n
     * <p/>
     * POST
     * <p/>
     * - Second request, execute phase: postback map n
     * <p/>
     * REDIRECT
     * <p/>
     * - NavigationHandler do the redirect, requestMap data lost, called Flash.setRedirect(true)
     * <p/>
     * Current map n saved and put as postback map n
     * <p/>
     * GET
     * <p/>
     * - Third  request, restore view phase (create a new one): current map n+1
     * (isRedirect() should return true as javadoc says)
     * - Third  request, execute phase: skipped
     * - Third  request, render  phase: current map n+1
     * <p/>
     * In this way proper behavior is preserved even in the case of redirect, since the GET part is handled as
     * the "render" part of the current traversal, keeping the semantic of flash object.
     *
     * @return
     */
    private Map<String, Object> getCurrentPhaseMap()
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        if (PhaseId.RENDER_RESPONSE.equals(facesContext.getCurrentPhaseId())
                || !facesContext.isPostback() || isRedirect())
        {
            return getCurrentRequestMap(facesContext);
        }
        else
        {
            return getPostbackRequestMap(facesContext);
        }
    }

    private void _removeAllChildren(FacesContext facesContext)
    {
        Map<String, Object> map = getPostbackRequestMap(facesContext);

        // Clear everything - note that because of naming conventions,
        // this will in fact automatically recurse through all children
        // grandchildren etc. - which is kind of a design flaw of SubKeyMap,
        // but one we're relying on
        map.clear();
    }

    /**
     *
     */
    @Override
    public void doPrePhaseActions(FacesContext facesContext)
    {
        Map<String, Object> requestMap = facesContext.getExternalContext()
                .getRequestMap();

        if (PhaseId.RESTORE_VIEW.equals(facesContext.getCurrentPhaseId()))
        {
            // Generate token and put on requestMap
            // It is necessary to set this token always, because on the next request
            // it should be possible to change postback map.
            String currentToken = _getNextToken();
            requestMap.put(FLASH_CURRENT_MAP_KEY, currentToken);

            if (facesContext.isPostback())
            {
                //Retore token
                String previousToken = _getPostbackMapKey(facesContext
                        .getExternalContext());

                if (previousToken != null)
                {
                    requestMap.put(FLASH_POSTBACK_MAP_KEY, previousToken);
                }
            }

            if (isKeepMessages())
            {
                restoreMessages(facesContext);
            }
        }

        //
        if (PhaseId.RENDER_RESPONSE.equals(facesContext.getCurrentPhaseId()))
        {
            // Put current map on next previous map
            // but only if this request is not a redirect
            if (!isRedirect())
            {
                _addPostbackMapKey(facesContext.getExternalContext());
            }
        }
    }

    @Override
    public void doPostPhaseActions(FacesContext facesContext)
    {
        if (PhaseId.RENDER_RESPONSE.equals(facesContext.getCurrentPhaseId()))
        {
            //Remove previous flash from session
            Map<String, Object> requestMap = facesContext.getExternalContext()
                    .getRequestMap();
            String token = (String) requestMap.get(FLASH_POSTBACK_MAP_KEY);

            if (token != null)
            {
                _removeAllChildren(facesContext);
            }

            if (isKeepMessages())
            {
                saveMessages(facesContext);
            }
        }
        else if (isRedirect()
                && (facesContext.getResponseComplete() || facesContext
                        .getRenderResponse()))
        {
            if (isKeepMessages())
            {
                saveMessages(facesContext);
            }
        }
    }

    private static class MessageEntry implements Serializable
    {
        private final Object clientId;
        private final Object message;

        public MessageEntry(Object clientId, Object message)
        {
            this.clientId = clientId;
            this.message = message;
        }
    }

    protected void saveMessages(FacesContext facesContext)
    {
        List<MessageEntry> messageList = null;

        Iterator<String> iterClientIds = facesContext
                .getClientIdsWithMessages();
        while (iterClientIds.hasNext())
        {
            String clientId = (String) iterClientIds.next();
            Iterator<FacesMessage> iterMessages = facesContext
                    .getMessages(clientId);

            while (iterMessages.hasNext())
            {
                FacesMessage message = iterMessages.next();

                if (messageList == null)
                {
                    messageList = new ArrayList<MessageEntry>();
                }
                messageList.add(new MessageEntry(clientId, message));
            }
        }

        if (messageList != null)
        {
            if (isRedirect())
            {
                getPostbackRequestMap(facesContext).put(
                        FLASH_KEEP_MESSAGES_LIST, messageList);
            }
            else
            {
                getCurrentRequestMap(facesContext).put(
                        FLASH_KEEP_MESSAGES_LIST, messageList);
            }
        }
    }

    protected void restoreMessages(FacesContext facesContext)
    {
        Map<String, Object> postbackMap = getPostbackRequestMap(facesContext);
        List<MessageEntry> messageList = (List<MessageEntry>) postbackMap
                .get(FLASH_KEEP_MESSAGES_LIST);

        if (messageList != null)
        {
            Iterator iterMessages = messageList.iterator();

            while (iterMessages.hasNext())
            {
                MessageEntry message = (MessageEntry) iterMessages.next();
                facesContext.addMessage((String) message.clientId,
                        (FacesMessage) message.message);
            }

            postbackMap.remove(FLASH_KEEP_MESSAGES_LIST);
        }
    }

    /**
     * Retrieve the postback map key
     */
    private String _getPostbackMapKey(ExternalContext externalContext)
    {
        String token = null;
        Object response = externalContext.getResponse();
        if (response instanceof HttpServletResponse)
        {
            //Use a cookie
            Cookie cookie = (Cookie) externalContext.getRequestCookieMap().get(
                    FLASH_POSTBACK_MAP_KEY);
            if (cookie != null)
            {
                token = cookie.getValue();
            }
        }
        else
        {
            //Use HttpSession or PortletSession object
            Map<String, Object> sessionMap = externalContext.getSessionMap();
            token = (String) sessionMap.get(FLASH_POSTBACK_MAP_KEY);
        }
        return token;
    }

    /**
     * Take the current map key and store it as a postback key for the next request.
     *
     * @param externalContext
     */
    private void _addPostbackMapKey(ExternalContext externalContext)
    {
        Object response = externalContext.getResponse();
        String token = (String) externalContext.getRequestMap().get(
                FLASH_CURRENT_MAP_KEY);

        //Use HttpSession or PortletSession object
        Map<String, Object> sessionMap = externalContext.getSessionMap();
        sessionMap.put(FLASH_POSTBACK_MAP_KEY, token);
    }

    /**
     * For check if there is a redirect we to take into accout this points:
     * <p/>
     * 1. isRedirect() could be accessed many times during the same
     * request.
     * 2. According to Post-Redirect-Get pattern, we cannot
     * ensure request scope values are preserved.
     */
    @Override
    public boolean isRedirect()
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        Map<String, Object> requestMap = externalContext.getRequestMap();
        Boolean redirect = (Boolean) requestMap.get(FLASH_REDIRECT);
        if (redirect == null)
        {
            Object response = externalContext.getResponse();
            if (response instanceof HttpServletResponse)
            {
                // Request values are lost after a redirect. We can create a
                // temporal cookie to pass the params between redirect calls.
                // It is better than use HttpSession object, because this cookie
                // is never sent by the server.
                Cookie cookie = (Cookie) externalContext.getRequestCookieMap()
                        .get(FLASH_REDIRECT);
                if (cookie != null)
                {
                    redirect = Boolean.TRUE;
                    HttpServletResponse httpResponse = (HttpServletResponse) response;
                    // A redirect happened, so it is safe to remove the cookie, setting
                    // the maxAge to 0 seconds. The effect is we passed FLASH_REDIRECT param
                    // to this request object
                    cookie.setMaxAge(0);
                    cookie.setValue(null);
                    httpResponse.addCookie(cookie);
                    requestMap.put(FLASH_REDIRECT, redirect);
                }
                else
                {
                    redirect = Boolean.FALSE;
                }
            }
            else
            {
                // Note that on portlet world we can't create cookies,
                // so we are forced to use the session map. Anyway,
                // according to the Bridge implementation(for example see
                // org.apache.myfaces.portlet.faces.bridge.BridgeImpl)
                // session object is created at start faces request
                Map<String, Object> sessionMap = externalContext
                        .getSessionMap();
                redirect = (Boolean) sessionMap.get(FLASH_REDIRECT);
                if (redirect != null)
                {
                    sessionMap.remove(FLASH_REDIRECT);
                    requestMap.put(FLASH_REDIRECT, redirect);
                }
                else
                {
                    redirect = Boolean.FALSE;
                }
            }
        }
        return redirect;
    }

    @Override
    public void setRedirect(boolean redirect)
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        Map<String, Object> requestMap = externalContext.getRequestMap();

        Boolean previousRedirect = (Boolean) requestMap.get(FLASH_REDIRECT);
        previousRedirect = (previousRedirect == null) ? Boolean.FALSE
                : previousRedirect;

        if (!previousRedirect.booleanValue() && redirect)
        {
            // This request contains a redirect. This condition is in general
            // triggered by a NavigationHandler. After a redirect all request scope
            // values get lost, so in order to preserve this value we need to
            // pass it between request. One strategy is use a cookie that is never sent
            // to the client. Other alternative is use the session map.
            externalContext.getSessionMap().put(FLASH_REDIRECT, redirect);
        }
        requestMap.put(FLASH_REDIRECT, redirect);
    }

    /**
     * In few words take a value from request scope map and put it on current request map,
     * so it is visible on the next request.
     */
    @Override
    public void keep(String key)
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        Map<String, Object> requestMap = facesContext.getExternalContext()
                .getRequestMap();
        Object value = requestMap.get(key);
        getCurrentRequestMap(facesContext).put(key, value);
    }

    /**
     * This is just an alias for request scope map.
     */
    @Override
    public void putNow(String key, Object value)
    {
        FacesContext.getCurrentInstance().getExternalContext().getRequestMap()
                .put(key, value);
    }

    @Override
    public boolean isKeepMessages()
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        Map<String, Object> requestMap = externalContext.getRequestMap();
        Boolean keepMessages = (Boolean) requestMap.get(FLASH_KEEP_MESSAGES);
        if (keepMessages == null)
        {
            Object response = externalContext.getResponse();
            if (response instanceof HttpServletResponse)
            {
                // Request values are lost after a redirect. We can create a
                // temporal cookie to pass the params between redirect calls.
                // It is better than use HttpSession object, because this cookie
                // is never sent by the server.
                Cookie cookie = (Cookie) externalContext.getRequestCookieMap()
                        .get(FLASH_KEEP_MESSAGES);
                if (cookie != null)
                {
                    keepMessages = Boolean.TRUE;
                    HttpServletResponse httpResponse = (HttpServletResponse) response;
                    // It is safe to remove the cookie, setting
                    // the maxAge to 0 seconds. The effect is we passed FLASH_KEEP_MESSAGES param
                    // to this request object
                    cookie.setMaxAge(0);
                    cookie.setValue(null);
                    httpResponse.addCookie(cookie);
                    requestMap.put(FLASH_KEEP_MESSAGES, keepMessages);
                }
                else
                {
                    keepMessages = Boolean.FALSE;
                }
            }
            else
            {
                // Note that on portlet world we can't create cookies,
                // so we are forced to use the session map. Anyway,
                // according to the Bridge implementation(for example see
                // org.apache.myfaces.portlet.faces.bridge.BridgeImpl)
                // session object is created at start faces request
                Map<String, Object> sessionMap = externalContext
                        .getSessionMap();
                keepMessages = (Boolean) sessionMap.get(FLASH_KEEP_MESSAGES);
                if (keepMessages != null)
                {
                    sessionMap.remove(FLASH_KEEP_MESSAGES);
                    requestMap.put(FLASH_KEEP_MESSAGES, keepMessages);
                }
                else
                {
                    keepMessages = Boolean.FALSE;
                }
            }
        }
        return keepMessages;
    }

    /**
     * If this property is true, the messages should be keep for the next request, no matter
     * if it is a normal postback case or a post-redirect-get case.
     */
    @Override
    public void setKeepMessages(boolean keepMessages)
    {
        FacesContext facesContext = FacesContext.getCurrentInstance();
        ExternalContext externalContext = facesContext.getExternalContext();
        Map<String, Object> requestMap = externalContext.getRequestMap();

        Boolean previousKeepMessages = (Boolean) requestMap
                .get(FLASH_KEEP_MESSAGES);
        previousKeepMessages = (previousKeepMessages == null) ? Boolean.FALSE
                : previousKeepMessages;

        if (!previousKeepMessages.booleanValue() && keepMessages)
        {
            externalContext.getSessionMap().put(FLASH_KEEP_MESSAGES,
                    keepMessages);
        }
        requestMap.put(FLASH_KEEP_MESSAGES, keepMessages);
    }

    public void clear()
    {
        getCurrentPhaseMap().clear();
    }

    public boolean containsKey(Object key)
    {
        return getCurrentPhaseMap().containsKey(key);
    }

    public boolean containsValue(Object value)
    {
        return getCurrentPhaseMap().containsValue(value);
    }

    public Set<Entry<String, Object>> entrySet()
    {
        return getCurrentPhaseMap().entrySet();
    }

    public Object get(Object key)
    {
        if (key == null)
        {
            return null;
        }

        if ("keepMessages".equals(key))
        {
            return isKeepMessages();
        }
        else if ("redirect".equals(key))
        {
            return isRedirect();
        }

        FacesContext context = FacesContext.getCurrentInstance();
        Map<String, Object> postbackMap = getPostbackRequestMap(context);
        Object returnValue = null;

        if (postbackMap != null)
        {
            returnValue = postbackMap.get(key);
        }

        return returnValue;
    }

    public boolean isEmpty()
    {
        return getCurrentPhaseMap().isEmpty();
    }

    public Set<String> keySet()
    {
        return getCurrentPhaseMap().keySet();
    }

    public Object put(String key, Object value)
    {
        if (key == null)
        {
            return null;
        }

        if ("keepMessages".equals(key))
        {
            Boolean booleanValue = convertToBoolean(value);
            this.setKeepMessages(booleanValue);
            return booleanValue;
        }
        else if ("redirect".equals(key))
        {
            Boolean booleanValue = convertToBoolean(value);
            this.setRedirect(booleanValue);
            return booleanValue;
        }
        else
        {
            Object returnValue = getCurrentPhaseMap().put(key, value);
            return returnValue;
        }
    }

    private Boolean convertToBoolean(Object value)
    {
        Boolean booleanValue;
        if (value instanceof Boolean)
        {
            booleanValue = (Boolean) value;
        }
        else
        {
            booleanValue = Boolean.parseBoolean(value.toString());
        }
        return booleanValue;
    }

    public void putAll(Map<? extends String, ? extends Object> m)
    {
        getCurrentPhaseMap().putAll(m);
    }

    public Object remove(Object key)
    {
        return getCurrentPhaseMap().remove(key);
    }

    public int size()
    {
        return getCurrentPhaseMap().size();
    }

    public Collection<Object> values()
    {
        return getCurrentPhaseMap().values();
    }

}
