/*
 * $Id: PortletUrlHelper.java 582626 2007-10-07 13:26:12Z mrdon $
 *
 * 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.portlet.util;

import static org.apache.struts2.portlet.PortletConstants.ACTION_PARAM;
import static org.apache.struts2.portlet.PortletConstants.MODE_PARAM;

import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.StringTokenizer;

import javax.portlet.PortletMode;
import javax.portlet.PortletRequest;
import javax.portlet.PortletSecurityException;
import javax.portlet.PortletURL;
import javax.portlet.RenderResponse;
import javax.portlet.WindowState;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.StrutsException;
import org.apache.struts2.portlet.context.PortletActionContext;

import com.opensymphony.xwork2.util.logging.Logger;
import com.opensymphony.xwork2.util.logging.LoggerFactory;

/**
 * Helper class for creating Portlet URLs. Portlet URLs are fundamentally different from regular
 * servlet URLs since they never target the application itself; all requests go through the portlet
 * container and must therefore be programatically constructed using the
 * {@link javax.portlet.MimeResponse#createActionURL()} and
 * {@link javax.portlet.MimeResponse#createRenderURL()} APIs.
 *
 */
public class PortletUrlHelper {
    public static final String ENCODING = "UTF-8";

    private static final Logger LOG = LoggerFactory.getLogger(PortletUrlHelper.class);

    protected static final String PORTLETMODE_NAME_EDIT = "edit";
    protected static final String PORTLETMODE_NAME_VIEW = "view";
    protected static final String PORTLETMODE_NAME_HELP = "help";

    protected static final String URLTYPE_NAME_ACTION = "action";
    protected static final String URLTYPE_NAME_RESOURCE = "resource";

    /**
     * Create a portlet URL with for the specified action and namespace.
     *
     * @param action The action the URL should invoke.
     * @param namespace The namespace of the action to invoke.
     * @param method The method of the action to invoke.
     * @param params The parameters of the URL.
     * @param type The type of the url, either <tt>action</tt> or <tt>render</tt>
     * @param mode The PortletMode of the URL.
     * @param state The WindowState of the URL.
     * @return The URL String.
     */
    public String buildUrl(String action, String namespace, String method, Map<String, Object> params,
            String type, String mode, String state) {
        return buildUrl(action, namespace, method, params, null, type, mode, state,
                true, true);
    }

    /**
     * Create a portlet URL with for the specified action and namespace.
     *
     * @see #buildUrl(String, String, String, java.util.Map, String, String, String)
     */
    public String buildUrl(String action, String namespace, String method, Map<String, Object> params,
            String scheme, String type, String portletMode, String windowState,
            boolean includeContext, boolean encodeResult) {
    	StringBuffer resultingAction = new StringBuffer();
        PortletRequest request = PortletActionContext.getRequest();
        LOG.debug("Creating url. Action = " + action + ", Namespace = "
                + namespace + ", Type = " + type);
        namespace = prependNamespace(namespace, portletMode, !URLTYPE_NAME_RESOURCE.equalsIgnoreCase(type));
        if (StringUtils.isEmpty(portletMode)) {
            portletMode = PortletActionContext.getRequest().getPortletMode().toString();
        }
        int paramStartIndex = action.indexOf('?');
        if (paramStartIndex > 0) {
            String value = action;
            action = value.substring(0, value.indexOf('?'));
            String queryStr = value.substring(paramStartIndex + 1);
            StringTokenizer tok = new StringTokenizer(queryStr, "&");
            while (tok.hasMoreTokens()) {
                String paramVal = tok.nextToken();
                String key = paramVal.substring(0, paramVal.indexOf('='));
                String val = paramVal.substring(paramVal.indexOf('=') + 1);
                params.put(key, new String[] { val });
            }
        }
        if (StringUtils.isNotEmpty(namespace)) {
            resultingAction.append(namespace);
            if(!action.startsWith("/") && !namespace.endsWith("/")) {
                resultingAction.append("/");
            }
        }
        resultingAction.append(action);
        if(StringUtils.isNotEmpty(method)) {
        	resultingAction.append("!").append(method);
        }
        if (LOG.isDebugEnabled()) LOG.debug("Resulting actionPath: " + resultingAction);
        params.put(ACTION_PARAM, new String[] { resultingAction.toString() });
        params.put(MODE_PARAM, new String[]{portletMode});
        final Map<String, String[]> portletParams = ensureParamsAreStringArrays(params);

        Object url = createUrl(scheme, type, portletParams);
        if(url instanceof PortletURL) {
        	try {
                final PortletURL portletUrl = (PortletURL) url;
                portletUrl.setPortletMode(getPortletMode(request, portletMode));
        		portletUrl.setWindowState(getWindowState(request, windowState));
        	} catch (Exception e) {
        		LOG.error("Unable to set mode or state:" + e.getMessage(), e);
        	}
        }

        String result = url.toString();
        // TEMP BUG-WORKAROUND FOR DOUBLE ESCAPING OF AMPERSAND
        if(result.indexOf("&amp;") >= 0) {
            result = result.replace("&amp;", "&");
        }
        return result;

    }

    protected Object createUrl( String scheme, String type, Map<String, String[]> portletParams ) {
        RenderResponse response = PortletActionContext.getRenderResponse();
        PortletURL url;
        if (URLTYPE_NAME_ACTION.equalsIgnoreCase(type)) {
            if (LOG.isDebugEnabled()) LOG.debug("Creating action url");
            url = response.createActionURL();
        }
        else {
            if (LOG.isDebugEnabled()) LOG.debug("Creating render url");
            url = response.createRenderURL();
        }

        url.setParameters(portletParams);

        if ("HTTPS".equalsIgnoreCase(scheme)) {
            try {
                url.setSecure(true);
            } catch ( PortletSecurityException e) {
                LOG.error("Cannot set scheme to https", e);
            }
        }
        return url;
    }

    /**
     * Prepend the namespace configuration for the specified namespace and PortletMode.
     *
     * @param namespace            The base namespace.
     * @param portletMode          The PortletMode.
     * @param prependModeNamespace In JSR286, the new URL type resource was added, which does not operate in the context
     *                             of a portlet mode. If the URL to create is of type resource, this parameter should be
     *                             set to false. Set it to true in any other case.
     * @return prepended namespace.
     */
    private String prependNamespace(String namespace, String portletMode, boolean prependModeNamespace) {
        StringBuffer sb = new StringBuffer();
        String modeNamespace;
        if (prependModeNamespace) {
            PortletMode mode = PortletActionContext.getRequest().getPortletMode();
            if(StringUtils.isNotEmpty(portletMode)) {
                mode = new PortletMode(portletMode);
            }
            modeNamespace = (String)PortletActionContext.getModeNamespaceMap().get(mode);
        } else {
            modeNamespace = null;
        }
        String portletNamespace = PortletActionContext.getPortletNamespace();
        if (LOG.isDebugEnabled()) {
            LOG.debug("PortletNamespace: " + portletNamespace + ", modeNamespace: "
                    + (modeNamespace!=null ? modeNamespace : "IGNORED"));
        }
        if(StringUtils.isNotEmpty(portletNamespace)) {
            sb.append(portletNamespace);
        }
        if(StringUtils.isNotEmpty(modeNamespace)) {
            if(!modeNamespace.startsWith("/")) {
                sb.append("/");
            }
            sb.append(modeNamespace);
        }
        if(StringUtils.isNotEmpty(namespace)) {
            if(!namespace.startsWith("/")) {
                sb.append("/");
            }
            sb.append(namespace);
        }
        if (LOG.isDebugEnabled()) LOG.debug("Resulting namespace: " + sb);
        return sb.toString();
    }

    /**
     * Encode an url to a non Struts action resource, like stylesheet, image or
     * servlet.
     *
     * @param value
     * @return encoded url to non Struts action resources.
     */
    public String buildResourceUrl(String value, Map params) {
        StringBuffer sb = new StringBuffer();
        // Relative URLs are not allowed in a portlet
        if (!value.startsWith("/")) {
            sb.append("/");
        }
        sb.append(value);
        if(params != null && params.size() > 0) {
            sb.append("?");
            Iterator it = params.keySet().iterator();
            try {
            while(it.hasNext()) {
                String key = (String)it.next();
                String val = (String)params.get(key);

                sb.append(URLEncoder.encode(key, ENCODING)).append("=");
                sb.append(URLEncoder.encode(val, ENCODING));
                if(it.hasNext()) {
                    sb.append("&");
                }
            }
            } catch (UnsupportedEncodingException e) {
                throw new StrutsException("Encoding "+ENCODING+" not found");
            }
        }
        PortletRequest req = PortletActionContext.getRequest();
        return encodeUrl(sb, req);
    }

    protected String encodeUrl( StringBuffer sb, PortletRequest req ) {
        RenderResponse resp = PortletActionContext.getRenderResponse();
        return resp.encodeURL(req.getContextPath() + sb.toString());
    }

    /**
     * Will ensure that all entries in <code>params</code> are String arrays,
     * as requried by the setParameters on the PortletURL.
     *
     * @param params The parameters to the URL.
     * @return A Map with all parameters as String arrays.
     */
    public static Map<String, String[]> ensureParamsAreStringArrays(Map<String, Object> params) {
        Map<String, String[]> result = null;
        if (params != null) {
            result = new LinkedHashMap<String, String[]>(params.size());
            for ( String key : params.keySet() ) {
                Object val = params.get(key);
                if (val instanceof String[]) {
                    result.put(key, (String[]) val);
                } else {
                    result.put(key, new String[]{val.toString()});
                }
            }
        }
        return result;
    }

    /**
     * Convert the given String to a WindowState object.
     *
     * @param portletReq The PortletRequest.
     * @param windowState The WindowState as a String.
     * @return The WindowState that mathces the <tt>windowState</tt> String, or if
     * the String is blank, the current WindowState.
     */
    private WindowState getWindowState(PortletRequest portletReq,
            String windowState) {
        WindowState state = portletReq.getWindowState();
        if (StringUtils.isNotEmpty(windowState)) {
            if ("maximized".equalsIgnoreCase(windowState)) {
                state = WindowState.MAXIMIZED;
            } else if ("normal".equalsIgnoreCase(windowState)) {
                state = WindowState.NORMAL;
            } else if ("minimized".equalsIgnoreCase(windowState)) {
                state = WindowState.MINIMIZED;
            }
        }
        if(state == null) {
            state = WindowState.NORMAL;
        }
        return state;
    }

    /**
     * Convert the given String to a PortletMode object.
     *
     * @param portletReq The PortletRequest.
     * @param portletMode The PortletMode as a String.
     * @return The PortletMode that mathces the <tt>portletMode</tt> String, or if
     * the String is blank, the current PortletMode.
     */
    private PortletMode getPortletMode(PortletRequest portletReq,
            String portletMode) {
        PortletMode mode = portletReq.getPortletMode();

        if (StringUtils.isNotEmpty(portletMode)) {
            if (PORTLETMODE_NAME_EDIT.equalsIgnoreCase(portletMode)) {
                mode = PortletMode.EDIT;
            } else if (PORTLETMODE_NAME_VIEW.equalsIgnoreCase(portletMode)) {
                mode = PortletMode.VIEW;
            } else if (PORTLETMODE_NAME_HELP.equalsIgnoreCase(portletMode)) {
                mode = PortletMode.HELP;
            }
        }
        if(mode == null) {
            mode = PortletMode.VIEW;
        }
        return mode;
    }
}
