/*
 * 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 flex.messaging.endpoints;

import flex.management.runtime.messaging.endpoints.EndpointControl;
import flex.messaging.FlexContext;
import flex.messaging.FlexSession;
import flex.messaging.HttpFlexSession;
import flex.messaging.MessageClient;
import flex.messaging.client.FlexClient;
import flex.messaging.config.ConfigMap;
import flex.messaging.config.ConfigurationConstants;
import flex.messaging.endpoints.amf.AMFFilter;
import flex.messaging.io.MessageIOConstants;
import flex.messaging.io.amf.ActionContext;
import flex.messaging.log.HTTPRequestLog;
import flex.messaging.messages.CommandMessage;
import flex.messaging.messages.Message;
import flex.messaging.util.SettingsReplaceUtil;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * Abstract base class for all the HTTP-based endpoints.
 */
public abstract class BaseHTTPEndpoint extends AbstractEndpoint
{
    //--------------------------------------------------------------------------
    //
    // Public Static Constants
    //
    //--------------------------------------------------------------------------

    /**
     * The secure and insecure URL schemes for the HTTP endpoint.
     */
    public static final String HTTP_PROTOCOL_SCHEME = "http";
    public static final String HTTPS_PROTOCOL_SCHEME = "https";

    //--------------------------------------------------------------------------
    //
    // Private Static Constants
    //
    //--------------------------------------------------------------------------

    private static final String ADD_NO_CACHE_HEADERS = "add-no-cache-headers";
    private static final String REDIRECT_URL = "redirect-url";
    private static final String INVALIDATE_SESSION_ON_DISCONNECT = "invalidate-session-on-disconnect";
    private static final String HTTP_RESPONSE_HEADERS = "http-response-headers";
    private static final String HEADER_ATTR = "header";

    private static final String HEADER_NAME_ORIGIN = "Origin";
    private static final String ACCESS_CONTROL = "Access-Control-";
    private static final String SESSION_REWRITING_ENABLED = "session-rewriting-enabled";

    private static final int ERR_MSG_DUPLICATE_SESSIONS_DETECTED = 10035;
    private static final String REQUEST_ATTR_DUPLICATE_SESSION_FLAG = "flex.messaging.request.DuplicateSessionDetected";

    //--------------------------------------------------------------------------
    //
    // Constructor
    //
    //--------------------------------------------------------------------------

    /**
     * Constructs an unmanaged <code>BaseHTTPEndpoint</code>.
     */
    public BaseHTTPEndpoint()
    {
        this(false);
    }

    /**
     * Constructs a <code>BaseHTTPEndpoint</code> with the specified management setting.
     *
     * @param enableManagement <code>true</code> if the <code>BaseHTTPEndpoint</code>
     * is manageable; otherwise <code>false</code>.
     */
    public BaseHTTPEndpoint(boolean enableManagement)
    {
        super(enableManagement);
    }

    //--------------------------------------------------------------------------
    //
    // Initialize, validate, start, and stop methods.
    //
    //--------------------------------------------------------------------------

    /**
     * Initializes the <code>Endpoint</code> with the properties.
     * If subclasses override this method, they must call <code>super.initialize()</code>.
     *
     * @param id The ID of the <code>Endpoint</code>.
     * @param properties Properties for the <code>Endpoint</code>.
     */
    @Override public void initialize(String id, ConfigMap properties)
    {
        super.initialize(id, properties);

        if (properties == null || properties.size() == 0)
            return;

        // General HTTP props.
        addNoCacheHeaders = properties.getPropertyAsBoolean(ADD_NO_CACHE_HEADERS, true);
        redirectURL = properties.getPropertyAsString(REDIRECT_URL, null);
        invalidateSessionOnDisconnect = properties.getPropertyAsBoolean(INVALIDATE_SESSION_ON_DISCONNECT, false);
        loginAfterDisconnect = properties.getPropertyAsBoolean(ConfigurationConstants.LOGIN_AFTER_DISCONNECT_ELEMENT, false);
        sessionRewritingEnabled = properties.getPropertyAsBoolean(SESSION_REWRITING_ENABLED, true);
        initializeHttpResponseHeaders(properties);
        validateEndpointProtocol();
    }

    /**
     * Starts the <code>Endpoint</code> by creating a filter chain and setting
     * up serializers and deserializers.
     */
    @Override public void start()
    {
        if (isStarted())
            return;

        super.start();

        filterChain = createFilterChain();
    }

    //--------------------------------------------------------------------------
    //
    // Variables
    //
    //--------------------------------------------------------------------------

    /**
     * Controller used to manage this endpoint.
     */
    protected EndpointControl controller;

    /**
     * AMF processing filter chain used by this endpoint.
     */
    protected AMFFilter filterChain;

    /**
     * Headers to add to the HTTP response.
     */
    protected List<HttpHeader> httpResponseHeaders;

    //--------------------------------------------------------------------------
    //
    // Properties
    //
    //--------------------------------------------------------------------------

    //----------------------------------
    //  addNoCacheHeaders
    //----------------------------------

    protected boolean addNoCacheHeaders = true;

    /**
     * Retrieves the <code>add-no-cache-headers</code> property.
     *
     * @return <code>true</code> if <code>add-no-cache-headers</code> is enabled;
     * <code>false</code> otherwise.
     */
    public boolean isAddNoCacheHeaders()
    {
        return addNoCacheHeaders;
    }

    /**
     * Sets the <code>add-no-cache-headers</code> property.
     *
     * @param addNoCacheHeaders The <code>add-no-cache-headers</code> property.
     */
    public void setAddNoCacheHeaders(boolean addNoCacheHeaders)
    {
        this.addNoCacheHeaders = addNoCacheHeaders;
    }

    //----------------------------------
    //  loginAfterDisconnect
    //----------------------------------

    /**
     *
     * This is a property used on the client.
     */
    protected boolean loginAfterDisconnect;

    //----------------------------------
    //  invalidateSessionOnDisconnect
    //----------------------------------

    protected boolean invalidateSessionOnDisconnect;

    /**
     * Indicates whether the server session will be invalidated
     * when a client channel disconnects.
     * The default is <code>false</code>.
     *
     * @return <code>true</code> if the server session will be invalidated
     *         when a client channel disconnects, <code>false</code> otherwise.
     */
    public boolean isInvalidateSessionOnDisconnect()
    {
        return invalidateSessionOnDisconnect;
    }

    /**
     * Determines whether to invalidate the server session for a client
     * that disconnects its channel.
     * The default is <code>false</code>.
     *
     * @param value <code>true</code> to invalidate the server session for a client
     *              that disconnects its channel, <code>false</code> otherwise.
     */
    public void setInvalidateSessionOnDisconnect(boolean value)
    {
        invalidateSessionOnDisconnect = value;
    }

    //----------------------------------
    //  redirectURL
    //----------------------------------

    protected String redirectURL;

    /**
     * Retrieves the <code>redirect-url</code> property.
     *
     * @return The <code>redirect-url</code> property.
     */
    public String getRedirectURL()
    {
        return redirectURL;
    }

    /**
     * Sets the <code>redirect-url</code> property.
     *
     * @param redirectURL The <code>redirect-url</code> property.
     */
    public void setRedirectURL(String redirectURL)
    {
        this.redirectURL = redirectURL;
    }

    //----------------------------------
    //  sessionRewritingEnabled
    //----------------------------------

    protected boolean sessionRewritingEnabled = true;

    /**
     * Indicates whether the server will fall back on rewriting URLs to include
     * session identifiers in the URL when HTTP session cookies are not allowed
     * on the client. The default is <code>true</code>.
     *
     * @return <code>true</code> if the session rewriting is enabled.
     */
    public boolean isSessionRewritingEnabled()
    {
        return sessionRewritingEnabled;
    }

    /**
     * Sets whether the session rewriting is enabled.
     *
     * @param value The session writing enabled value.
     */
    public void setSessionRewritingEnabled(boolean value)
    {
        sessionRewritingEnabled = value;
    }

    //--------------------------------------------------------------------------
    //
    // Public Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Handle AMF/AMFX encoded messages sent over HTTP.
     *
     * @param req The original servlet request.
     * @param res The active servlet response.
     */
    @Override
    public void service(HttpServletRequest req, HttpServletResponse res)
    {
        super.service(req, res);

        try
        {
            // Setup serialization and type marshalling contexts
            setThreadLocals();

            // Create a context for this request
            ActionContext context = new ActionContext();

            // Pass endpoint's mpi settings to the context so that it knows what level of
            // performance metrics should be gathered during serialization/deserialization
            context.setRecordMessageSizes(isRecordMessageSizes());
            context.setRecordMessageTimes(isRecordMessageTimes());

            // Send invocation through filter chain, which ends at the MessageBroker
            filterChain.invoke(context);

            // After serialization completes, increment endpoint byte counters,
            // if the endpoint is managed
            if (isManaged())
            {
                controller.addToBytesDeserialized(context.getDeserializedBytes());
                controller.addToBytesSerialized(context.getSerializedBytes());
            }

            if (context.getStatus() != MessageIOConstants.STATUS_NOTAMF)
            {
                if (addNoCacheHeaders)
                    addNoCacheHeaders(req, res);

                addHeadersToResponse(req, res);

                ByteArrayOutputStream outBuffer = context.getResponseOutput();

                res.setContentType(getResponseContentType());

                res.setContentLength(outBuffer.size());
                outBuffer.writeTo(res.getOutputStream());
                res.flushBuffer();
            }
            else
            {
                // Not an AMF request, probably viewed in a browser
                if (redirectURL != null)
                {
                    try
                    {
                        //Check for redirect URL context-root token
                        redirectURL = SettingsReplaceUtil.replaceContextPath(redirectURL, req.getContextPath());
                        res.sendRedirect(redirectURL);
                    }
                    catch (IllegalStateException alreadyFlushed)
                    {
                        // ignore
                    }
                }
            }
        }
        catch (IOException ioe)
        {
            // This happens when client closes the connection, log it at info level
            log.info(ioe.getMessage());
            // Store exception information for latter logging
            req.setAttribute(HTTPRequestLog.HTTP_ERROR_INFO, ioe.toString());
        }
        catch (Throwable t)
        {
            log.error(t.getMessage(), t);
            // Store exception information for latter logging
            req.setAttribute(HTTPRequestLog.HTTP_ERROR_INFO, t.toString());
        }
        finally
        {
            clearThreadLocals();
        }
    }


    /**
     *
     * Returns a <code>ConfigMap</code> of endpoint properties that the client
     * needs. This includes properties from <code>super.describeEndpoint</code>
     * and additional <code>BaseHTTPEndpoint</code> specific properties under
     * "properties" key.
     */
    @Override
    public ConfigMap describeEndpoint()
    {
        ConfigMap endpointConfig = super.describeEndpoint();

        if (loginAfterDisconnect)
        {
            ConfigMap loginAfterDisconnect = new ConfigMap();
            // Adding as a value rather than attribute to the parent
            loginAfterDisconnect.addProperty(EMPTY_STRING, TRUE_STRING);

            ConfigMap properties = endpointConfig.getPropertyAsMap(PROPERTIES_ELEMENT, null);
            if (properties == null)
            {
                properties = new ConfigMap();
                endpointConfig.addProperty(PROPERTIES_ELEMENT, properties);
            }
            properties.addProperty(ConfigurationConstants.LOGIN_AFTER_DISCONNECT_ELEMENT, loginAfterDisconnect);
        }

        return endpointConfig;
    }

    /**
     * Overrides to guard against duplicate HTTP-based sessions for the same FlexClient
     * which will occur if the remote host has disabled session cookies.
     *
     * @see AbstractEndpoint#setupFlexClient(String)
     */
    @Override
    public FlexClient setupFlexClient(String id)
    {
        FlexClient flexClient = super.setupFlexClient(id);

        // Scan for duplicate HTTP-sessions and if found, invalidate them and throw a MessageException.
        // A request attribute is used to deal with batched AMF messages that arrive in a single request by trigger multiple passes through this method.
        boolean duplicateSessionDetected = (FlexContext.getHttpRequest().getAttribute(REQUEST_ATTR_DUPLICATE_SESSION_FLAG) != null);

        List<FlexSession> sessions = null;
        if (!duplicateSessionDetected)
        {
            sessions = flexClient.getFlexSessions();
            int n = sessions.size();
            if (n > 1)
            {
                List<HttpFlexSession> httpFlexSessions = new ArrayList<HttpFlexSession>();
                for (int i = 0; i < n; i++)
                {
                    FlexSession currentSession = sessions.get(i);
                    if (currentSession instanceof HttpFlexSession)
                        httpFlexSessions.add((HttpFlexSession)currentSession);
                    if (httpFlexSessions.size() > 1)
                    {
                        FlexContext.getHttpRequest().setAttribute(REQUEST_ATTR_DUPLICATE_SESSION_FLAG, httpFlexSessions);
                        duplicateSessionDetected = true;
                        break;
                    }
                }
            }
        }

        // If more than one was found, remote host isn't using session cookies. Kill all duplicate sessions and return an error.
        // Simplest to just re-scan the list given that it will be very short, but use an iterator for concurrent modification.
        if (duplicateSessionDetected)
        {
            Object attributeValue = FlexContext.getHttpRequest().getAttribute(REQUEST_ATTR_DUPLICATE_SESSION_FLAG);
            String newSessionId = null;
            String oldSessionId = null;
            if (attributeValue != null)
            {
                @SuppressWarnings("unchecked")
                List<HttpFlexSession> httpFlexSessions = (List<HttpFlexSession>)attributeValue;
                oldSessionId = httpFlexSessions.get(0).getId();
                newSessionId = httpFlexSessions.get(1).getId();
            }

            if (sessions != null)
            {
                for (FlexSession session : sessions)
                {
                    if (session instanceof HttpFlexSession)
                    {
                        session.invalidate();
                    }
                }
            }

            // Return an error to the client.

            DuplicateSessionException e = new DuplicateSessionException();
            // Duplicate HTTP-based FlexSession error: A request for FlexClient ''{0}'' arrived over a new FlexSession ''{1}'', but FlexClient is already associated with FlexSession ''{2}'', therefore it cannot be associated with the new session.
            e.setMessage(ERR_MSG_DUPLICATE_SESSIONS_DETECTED, new Object[]{flexClient.getId(), newSessionId, oldSessionId});
            throw e;
        }

        return flexClient;
    }

    //--------------------------------------------------------------------------
    //
    // Protected Methods
    //
    //--------------------------------------------------------------------------

    /**
     * Adds custom headers specified in the config to the HTTP response. The only
     * exception is that access control headers (Access-Control-*) are sent only
     * if there is an Origin header in the request.
     *
     * @param request The HTTP request.
     * @param response The HTTP response.
     */
    protected void addHeadersToResponse(HttpServletRequest request, HttpServletResponse response)
    {
        if (httpResponseHeaders == null || httpResponseHeaders.isEmpty())
            return;

        String origin = request.getHeader(HEADER_NAME_ORIGIN);
        boolean originHeaderExists = origin != null && origin.length() != 0;

        for (HttpHeader header : httpResponseHeaders)
        {
            if (header.name.startsWith(ACCESS_CONTROL) && !originHeaderExists)
                continue;

            response.addHeader(header.name, header.value);
        }
    }

    /**
     * Create the gateway filters that transform action requests
     * and responses.
     */
    protected abstract AMFFilter createFilterChain();

    /**
     * Returns the content type used by the connection handler to set on the
     * HTTP response. Subclasses should either return MessageIOConstants.AMF_CONTENT_TYPE
     * or MessageIOConstants.XML_CONTENT_TYPE.
     */
    protected abstract String getResponseContentType();

    /**
     * Returns https which is the secure protocol scheme for the endpoint.
     *
     * @return https.
     */
    @Override protected String getSecureProtocolScheme()
    {
        return HTTPS_PROTOCOL_SCHEME;
    }

    /**
     * Returns http which is the insecure protocol scheme for the endpoint.
     *
     * @return http.
     */
    @Override protected String getInsecureProtocolScheme()
    {
        return HTTP_PROTOCOL_SCHEME;
    }

    /**
     * @see flex.messaging.endpoints.AbstractEndpoint#handleChannelDisconnect(CommandMessage)
     */
    @Override protected Message handleChannelDisconnect(CommandMessage disconnectCommand)
    {
        HttpFlexSession session = (HttpFlexSession)FlexContext.getFlexSession();
        FlexClient flexClient = FlexContext.getFlexClient();

        // Shut down any subscriptions established over this channel/endpoint
        // for this specific FlexClient.
        if (flexClient.isValid())
        {
            String endpointId = getId();
            List<MessageClient> messageClients = flexClient.getMessageClients();
            for (MessageClient messageClient : messageClients)
            {
                if (messageClient.getEndpointId().equals(endpointId))
                {
                    messageClient.setClientChannelDisconnected(true);
                    messageClient.invalidate();
                }
            }
        }

        // And optionally invalidate the session.
        if (session.isValid() && isInvalidateSessionOnDisconnect())
            session.invalidate(false /* don't recreate */);

        return super.handleChannelDisconnect(disconnectCommand);
    }

    protected void initializeHttpResponseHeaders(ConfigMap properties)
    {
        if (!properties.containsKey(HTTP_RESPONSE_HEADERS))
            return;

        ConfigMap httpResponseHeaders = properties.getPropertyAsMap(HTTP_RESPONSE_HEADERS, null);
        if (httpResponseHeaders == null)
            return;

        @SuppressWarnings("unchecked")
        List<String> headers = httpResponseHeaders.getPropertyAsList(HEADER_ATTR, null);
        if (headers == null || headers.isEmpty())
            return;

        if (this.httpResponseHeaders == null)
            this.httpResponseHeaders = new ArrayList<HttpHeader>();

        for (String header : headers)
        {
            int colonIndex = header.indexOf(":");
            String name = header.substring(0, colonIndex).trim();
            String value = header.substring(colonIndex + 1).trim();
            this.httpResponseHeaders.add(new HttpHeader(name, value));
        }
    }

    //--------------------------------------------------------------------------
    //
    // Nested Classes
    //
    //--------------------------------------------------------------------------

    /**
     * Helper class used for headers in the HTTP request/response.
     */
    static class HttpHeader
    {
        public HttpHeader(String name, String value)
        {
            this.name = name;
            this.value = value;
        }
        public final String name;
        public final String value;
    }
}