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

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.config.entities.ResultConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.reflection.ReflectionException;
import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.dispatcher.Dispatcher;
import org.apache.struts2.dispatcher.mapper.ActionMapper;
import org.apache.struts2.dispatcher.mapper.ActionMapping;
import org.apache.struts2.views.util.UrlHelper;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import static javax.servlet.http.HttpServletResponse.SC_FOUND;

/**
 * Calls the {@link HttpServletResponse#sendRedirect(String) sendRedirect}
 * method to the location specified. The response is told to redirect the
 * browser to the specified location (a new request from the client). The
 * consequence of doing this means that the action (action instance, action
 * errors, field errors, etc) that was just executed is lost and no longer
 * available. This is because actions are built on a single-thread model. The
 * only way to pass data is through the session or with web parameters
 * (url?name=value) which can be OGNL expressions.
 *
 * <b>This result type takes the following parameters:</b>
 *
 * <ul>
 * <li><b>location (default)</b> - the location to go to after execution.</li>
 * <li><b>parse</b> - true by default. If set to false, the location param will
 * not be parsed for Ognl expressions.</li>
 * <li><b>anchor</b> - Optional.  Also known as "fragment" or colloquially as
 * "hash".  You can specify an anchor for a result.</li>
 * </ul>
 * This result follows the same rules from {@link StrutsResultSupport}.
 *
 * <b>Example:</b>
 * <pre>
 * <!-- START SNIPPET: example -->
 * &lt;!--
 *   The redirect URL generated will be:
 *   /foo.jsp#FRAGMENT
 * --&gt;
 * &lt;result name="success" type="redirect"&gt;
 *   &lt;param name="location"&gt;foo.jsp&lt;/param&gt;
 *   &lt;param name="parse"&gt;false&lt;/param&gt;
 *   &lt;param name="anchor"&gt;FRAGMENT&lt;/param&gt;
 * &lt;/result&gt;
 * <!-- END SNIPPET: example -->
 * </pre>
 */
public class ServletRedirectResult extends StrutsResultSupport implements ReflectionExceptionHandler, Redirectable {

    private static final long serialVersionUID = 6316947346435301270L;

    private static final Logger LOG = LogManager.getLogger(ServletRedirectResult.class);

    protected boolean prependServletContext = true;
    protected ActionMapper actionMapper;
    protected int statusCode = SC_FOUND;
    protected boolean suppressEmptyParameters = false;
    protected Map<String, Object> requestParameters = new LinkedHashMap<>();
    protected String anchor;

    private UrlHelper urlHelper;

    public ServletRedirectResult() {
        super();
    }

    public ServletRedirectResult(String location) {
        this(location, null);
    }

    public ServletRedirectResult(String location, String anchor) {
        super(location);
        this.anchor = anchor;
    }

    @Inject
    public void setActionMapper(ActionMapper mapper) {
        this.actionMapper = mapper;
    }

    @Inject
    public void setUrlHelper(UrlHelper urlHelper) {
        this.urlHelper = urlHelper;
    }

    public void setStatusCode(int code) {
        this.statusCode = code;
    }

    /**
     * Set the optional anchor value.
     *
     * @param anchor the anchor value
     */
    public void setAnchor(String anchor) {
        this.anchor = anchor;
    }

    /**
     * Sets whether or not to prepend the servlet context path to the redirected
     * URL.
     *
     * @param prependServletContext <tt>true</tt> to prepend the location with the servlet context path, <tt>false</tt> otherwise.
     */
    public void setPrependServletContext(boolean prependServletContext) {
        this.prependServletContext = prependServletContext;
    }

    public void execute(ActionInvocation invocation) throws Exception {
        if (anchor != null) {
            anchor = conditionalParse(anchor, invocation);
        }
        super.execute(invocation);
    }

    /**
     * Redirects to the location specified by calling
     * {@link HttpServletResponse#sendRedirect(String)}.
     *
     * @param finalLocation the location to redirect to.
     * @param invocation    an encapsulation of the action execution state.
     * @throws Exception if an error occurs when redirecting.
     */
    protected void doExecute(String finalLocation, ActionInvocation invocation) throws Exception {
        ActionContext ctx = invocation.getInvocationContext();
        HttpServletRequest request = ctx.getServletRequest();
        HttpServletResponse response = ctx.getServletResponse();

        if (isPathUrl(finalLocation)) {
            if (!finalLocation.startsWith("/")) {
                ActionMapping mapping = actionMapper.getMapping(request, Dispatcher.getInstance().getConfigurationManager());
                String namespace = null;
                if (mapping != null) {
                    namespace = mapping.getNamespace();
                }

                if ((namespace != null) && (namespace.length() > 0) && (!"/".equals(namespace))) {
                    finalLocation = namespace + "/" + finalLocation;
                } else {
                    finalLocation = "/" + finalLocation;
                }
            }

            // if the URL's are relative to the servlet context, append the servlet context path
            if (prependServletContext && (request.getContextPath() != null) && (request.getContextPath().length() > 0)) {
                finalLocation = request.getContextPath() + finalLocation;
            }
        }
        ResultConfig resultConfig = invocation.getProxy().getConfig().getResults().get(invocation.getResultCode());
        if (resultConfig != null) {
            Map<String, String> resultConfigParams = resultConfig.getParams();

            List<String> prohibitedResultParams = getProhibitedResultParams();
            for (Map.Entry<String, String> e : resultConfigParams.entrySet()) {
                if (!prohibitedResultParams.contains(e.getKey())) {
                    Collection<String> values = conditionalParseCollection(e.getValue(), invocation, suppressEmptyParameters);
                    if (!suppressEmptyParameters || !values.isEmpty()) {
                        requestParameters.put(e.getKey(), values);
                    }
                }
            }
        }

        StringBuilder tmpLocation = new StringBuilder(finalLocation);
        urlHelper.buildParametersString(requestParameters, tmpLocation, "&");

        // add the anchor
        if (anchor != null) {
            tmpLocation.append('#').append(anchor);
        }

        finalLocation = response.encodeRedirectURL(tmpLocation.toString());

        LOG.debug("Redirecting to finalLocation: {}", finalLocation);

        sendRedirect(response, finalLocation);
    }

    protected List<String> getProhibitedResultParams() {
        return Arrays.asList(
            DEFAULT_PARAM,
            "namespace",
            "method",
            "encode",
            "parse",
            "location",
            "prependServletContext",
            "suppressEmptyParameters",
            "anchor",
            "statusCode"
        );
    }

    /**
     * Sends the redirection. Can be overridden to customize how the redirect is
     * handled (i.e. to use a different status code)
     *
     * @param response      The response
     * @param finalLocation The location URI
     * @throws IOException in case of IO errors
     */
    protected void sendRedirect(HttpServletResponse response, String finalLocation) throws IOException {
        try {
            if (SC_FOUND == statusCode) {
                response.sendRedirect(finalLocation);
            } else {
                response.setStatus(statusCode);
                response.setHeader("Location", finalLocation);
                try {
                    response.getWriter().write(finalLocation);
                } finally {
                    response.getWriter().close();
                }
            }
        } catch (IOException ioe) {
            LOG.warn("Unable to redirect to: {}, code: {}; {}", finalLocation, statusCode, ioe);
            throw ioe;  // Re-throw required to preserve existing default behaviour (no stacktrace in above warn for this reason)
        } catch (IllegalStateException ise) {
            LOG.warn("Unable to redirect to: {}, code: {}; isCommited: {}; {}", finalLocation, statusCode, response.isCommitted(), ise);
            throw ise;  // Re-throw required to preserve existing default behaviour (no stacktrace in above warn for this reason)
        }

    }

    /**
     * Checks if url is simple path or either full url
     *
     * @param url string
     * @return true if it's just a path not a full url
     */
    protected boolean isPathUrl(String url) {
        try {
            String rawUrl = url;
            if (url.contains("?")) {
                rawUrl = url.substring(0, url.indexOf('?'));
            }
            URI uri = URI.create(rawUrl.replaceAll(" ", "%20"));
            if (uri.isAbsolute()) {
                URL validUrl = uri.toURL();
                LOG.debug("[{}] is full url, not a path", url);
                return validUrl.getProtocol() == null;
            } else {
                LOG.debug("[{}] isn't absolute URI, assuming it's a path", url);
                return true;
            }
        } catch (IllegalArgumentException e) {
            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
            return true;
        } catch (MalformedURLException e) {
            LOG.debug("[{}] isn't a valid URL, assuming it's a path", url, e);
            return true;
        }
    }

    /**
     * Sets the suppressEmptyParameters option
     *
     * @param suppressEmptyParameters The new value for this option
     */
    public void setSuppressEmptyParameters(boolean suppressEmptyParameters) {
        this.suppressEmptyParameters = suppressEmptyParameters;
    }

    /**
     * Adds a request parameter to be added to the redirect url
     *
     * @param key   The parameter name
     * @param value The parameter value
     * @return the servlet redirect result
     */
    public ServletRedirectResult addParameter(String key, Object value) {
        requestParameters.put(key, String.valueOf(value));
        return this;
    }

    public void handle(ReflectionException ex) {
        // Only log as debug as they are probably parameters to be appended to the url
        if (LOG.isDebugEnabled()) {
            LOG.debug(ex.getMessage(), ex);
        }
    }

}
