package com.atlassian.bitbucket.util;

import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nullable;
import javax.servlet.ServletResponseWrapper;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

public class RequestUtils {

    private RequestUtils() {
        throw new UnsupportedOperationException(getClass().getName() +
                " is a utility class and should not be instantiated");
    }

    /**
     * This is designed bypass the {@code OAuthWWWAuthenticateAddingResponse} which adds a WWW-Authenticate: OAuth realm
     * header whenever setting a 401 status, causing Mercurial not to request the user for a username and password.
     *
     * @param resp the HttpServletResponse being serviced
     * @return the underlying HttpServletResponse for any ServletResponseWrapper
     */
    public static HttpServletResponse unwrap(HttpServletResponse resp) {
        while (resp instanceof ServletResponseWrapper) {
            resp = (HttpServletResponse) ((ServletResponseWrapper) resp).getResponse();
        }
        return resp;
    }

    /**
     * Returns the remote host for a  HttpServletRequest, taking into account the optional
     * X-Forwarded-For HTTP Header that is often added by proxy servers.
     *
     * @param request the request
     * @return the remote host name
     */
    public static String getRemoteHost(HttpServletRequest request) {
        String forwardedFor = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotEmpty(forwardedFor)) {
            String[] forwardedHostsChain = forwardedFor.split(",");
            // return the first non-empty string
            for (String hostname : forwardedHostsChain) {
                if (StringUtils.isNotBlank(hostname)) {
                    return hostname.trim();
                }
            }
        }
        return request.getRemoteHost();
    }

    /**
     * Checks whether the user-agent in the user agent is a browser
     * @param request the request
     * @return {@code true} if the user-agent is a browser
     */
    public static boolean isUserAgentBrowser(HttpServletRequest request) {
        String userAgent = StringUtils.lowerCase(request.getHeader("user-agent"));

        return userAgent != null && (userAgent.contains("mozilla") || userAgent.contains("opera"));
    }

    /**
     * If a param value for the given name exists, return the first one in a trimmed form; otherwise, return null.
     * <p>
     * If the parameter has multiple values, only the first one will be returned.
     *
     * @param paramName the name of the request parameter
     * @param requestParams the request parameters
     * @return the parameter's value or {@code null}
     */
    @Nullable
    public static String getParamValue(String paramName, Map<String, String[]> requestParams) {
        final String[] vals = requestParams.get(paramName);
        if (vals == null || vals.length == 0) {
            return null;
        }
        String val = vals[0];
        return StringUtils.isBlank(val) ? null : val.trim();
    }

}
