/*
 * 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.renderkit.html.base;

import org.apache.myfaces.renderkit.html.util.CommonPropertyUtils;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIParameter;
import javax.faces.component.ValueHolder;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.component.html.HtmlCommandButton;
import javax.faces.component.html.HtmlCommandLink;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.ActionEvent;

import org.apache.myfaces.renderkit.ClientBehaviorEvents;
import org.apache.myfaces.renderkit.html.util.JSFAttr;
import org.apache.myfaces.renderkit.RendererUtils;
import org.apache.myfaces.renderkit.html.util.JavascriptUtils;
import org.apache.myfaces.renderkit.html.util.ResourceUtils;
import org.apache.myfaces.renderkit.html.util.HTML;
import org.apache.myfaces.util.ComponentUtils;
import org.apache.myfaces.util.SharedStringBuilder;

public class HtmlButtonRendererBase extends HtmlRenderer
{
    private static final String SB_BUILD_BEHAVIORIZED_ONCLICK = HtmlButtonRendererBase.class.getName()
            + "#buildBehaviorizedOnClick";
    private static final String SB_BUILD_ONCLICK = HtmlButtonRendererBase.class.getName()
            + "#buildOnClick";
    private static final String SB_ADD_CHILD_PARAMETERS = HtmlButtonRendererBase.class.getName() +
            "#addChildParameters";
    
    private static final String IMAGE_BUTTON_SUFFIX_X = ".x";
    private static final String IMAGE_BUTTON_SUFFIX_Y = ".y";

    @Override
    public void decode(FacesContext facesContext, UIComponent uiComponent)
    {
        RendererUtils.checkParamValidity(facesContext, uiComponent, UICommand.class);

        //super.decode must not be called, because value is handled here
        boolean disabled = isDisabled(facesContext, uiComponent);
        // MYFACES-3960 Decode, decode client behavior and queue action event at the end
        boolean activateActionEvent = !isReset(uiComponent) && isSubmitted(facesContext, uiComponent) && !disabled;
        
        if (uiComponent instanceof ClientBehaviorHolder &&
                !disabled)
        {
            HtmlRendererUtils.decodeClientBehaviors(facesContext, uiComponent);
        }
        
        if (activateActionEvent)
        {
            uiComponent.queueEvent(new ActionEvent(uiComponent));
        }
    }

    private static boolean isReset(UIComponent uiComponent)
    {
        return "reset".equals((String) uiComponent.getAttributes().get(HTML.TYPE_ATTR));
    }
    
    private static boolean isButton(UIComponent uiComponent)
    {
        return "button".equals((String) uiComponent.getAttributes().get(HTML.TYPE_ATTR));
    }

    private static boolean isSubmitted(FacesContext facesContext, UIComponent uiComponent)
    {
        String clientId = uiComponent.getClientId(facesContext);
        Map paramMap = facesContext.getExternalContext().getRequestParameterMap();
        String hiddenLink = null;

        UIForm form = ComponentUtils.closest(UIForm.class, uiComponent);
        if (form != null)
        {
            hiddenLink = (String) facesContext.getExternalContext().getRequestParameterMap().get(
                HtmlRendererUtils.getHiddenCommandLinkFieldName(form, facesContext));
        }
        return paramMap.containsKey(clientId) || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_X) 
            || paramMap.containsKey(clientId + IMAGE_BUTTON_SUFFIX_Y)
            || (hiddenLink != null && hiddenLink.equals (clientId))
            || HtmlRendererUtils.isPartialOrBehaviorSubmit(facesContext, clientId);
    }

    @Override
    public void encodeBegin(FacesContext facesContext, UIComponent uiComponent) throws IOException
    {
        RendererUtils.checkParamValidity(facesContext, uiComponent, UICommand.class);

        String clientId = uiComponent.getClientId(facesContext);

        ResponseWriter writer = facesContext.getResponseWriter();
        
        // commandButton does not need to be nested in a form since JSF 2.0
        UIForm form = ComponentUtils.closest(UIForm.class, uiComponent);

        boolean reset = isReset(uiComponent);
        boolean button = isButton(uiComponent);

        Map<String, List<ClientBehavior>> behaviors = null;
        if (uiComponent instanceof ClientBehaviorHolder)
        {
            behaviors = ((ClientBehaviorHolder) uiComponent).getClientBehaviors();
            if (!behaviors.isEmpty())
            {
                ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
            }
        }

        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
                facesContext, getChildren(uiComponent), false, false);

        String commandOnclick = (String)uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
        
        if (commandOnclick != null && (validParams != null && !validParams.isEmpty()))
        {
            ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
        }

        writer.startElement(HTML.INPUT_ELEM, uiComponent);

        writer.writeAttribute(HTML.ID_ATTR, clientId, JSFAttr.ID_ATTR);
        writer.writeAttribute(HTML.NAME_ATTR, clientId, JSFAttr.ID_ATTR);

        String image = RendererUtils.getIconSrc(facesContext, uiComponent, JSFAttr.IMAGE_ATTR);
        if (image != null)
        {
            writer.writeAttribute(HTML.TYPE_ATTR, HTML.INPUT_TYPE_IMAGE, JSFAttr.TYPE_ATTR);
            writer.writeURIAttribute(HTML.SRC_ATTR, image, JSFAttr.IMAGE_ATTR);
        }
        else
        {
            String type = getType(uiComponent);

            if (type == null || (!reset && !button))
            {
                type = HTML.INPUT_TYPE_SUBMIT;
            }
            writer.writeAttribute(HTML.TYPE_ATTR, type, JSFAttr.TYPE_ATTR);
            Object value = getValue(uiComponent);
            if (value != null)
            {
                writer.writeAttribute(HTML.VALUE_ATTR, value, JSFAttr.VALUE_ATTR);
            }
        }
        
        if (HtmlRendererUtils.hasClientBehavior(ClientBehaviorEvents.CLICK, behaviors, facesContext)
                || HtmlRendererUtils.hasClientBehavior(ClientBehaviorEvents.ACTION, behaviors, facesContext))
        {
            if (!reset && !button)
            {
                String onClick = buildBehaviorizedOnClick(uiComponent, behaviors, facesContext, writer,
                        form, validParams);
                if (onClick.length() != 0)
                {
                    writer.writeAttribute(HTML.ONCLICK_ATTR, onClick, null);
                }
            }
            else
            {
                Collection<ClientBehaviorContext.Parameter> paramList = 
                    HtmlRendererUtils.getClientBehaviorContextParameters(
                        HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, uiComponent));
                    
                String onClick = HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent,
                        ClientBehaviorEvents.CLICK, paramList, ClientBehaviorEvents.ACTION, paramList, behaviors,
                        commandOnclick , null);
                if (onClick.length() != 0)
                {
                    writer.writeAttribute(HTML.ONCLICK_ATTR, onClick, null);
                }
            }
            
            Map<String, Object> attributes = uiComponent.getAttributes(); 
            
            HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent, ClientBehaviorEvents.DBLCLICK, null,
                    behaviors, (String) attributes.get(HTML.ONDBLCLICK_ATTR), "");
        }
        else
        {
            //fallback into the pre 2.0 code to keep backwards compatibility with libraries which rely on internals
            if (!reset && !button)
            {
                StringBuilder onClick = buildOnClick(uiComponent, facesContext, writer, validParams);
                if (onClick.length() != 0)
                {
                    writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
                }
            }
            else
            {
                HtmlRendererUtils.renderHTMLStringAttribute(writer, uiComponent, HTML.ONCLICK_ATTR, HTML.ONCLICK_ATTR);
            }
        }
        
        if (isCommonPropertiesOptimizationEnabled(facesContext))
        {
            CommonPropertyUtils.renderButtonPassthroughPropertiesWithoutDisabledAndEvents(writer, 
                    CommonPropertyUtils.getCommonPropertiesMarked(uiComponent), uiComponent);
        }
        else
        {
            HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
                                                   HTML.BUTTON_PASSTHROUGH_ATTRIBUTES_WITHOUT_DISABLED_AND_EVENTS);
        }

        if (behaviors != null && !behaviors.isEmpty())
        {
            HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(
                    facesContext, writer, uiComponent, behaviors);
            HtmlRendererUtils.renderBehaviorizedFieldEventHandlers(facesContext, writer, uiComponent, behaviors);
        }
        else
        {
            if (isCommonPropertiesOptimizationEnabled(facesContext))
            {
                long commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(uiComponent);
                CommonPropertyUtils.renderEventPropertiesWithoutOnclick(writer, commonPropertiesMarked, uiComponent);
                CommonPropertyUtils.renderCommonFieldEventProperties(writer, commonPropertiesMarked, uiComponent);
            }
            else
            {
                HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
                        HTML.EVENT_HANDLER_ATTRIBUTES_WITHOUT_ONCLICK);
                HtmlRendererUtils.renderHTMLAttributes(writer, uiComponent,
                        HTML.COMMON_FIELD_EVENT_ATTRIBUTES);
            }
        }

        if (isDisabled(facesContext, uiComponent))
        {
            writer.writeAttribute(HTML.DISABLED_ATTR, Boolean.TRUE, JSFAttr.DISABLED_ATTR);
        }
        
        if (isReadonly(facesContext, uiComponent))
        {
            writer.writeAttribute(HTML.READONLY_ATTR, Boolean.TRUE, JSFAttr.READONLY_ATTR);
        }
    }
    
    @Override
    public void encodeEnd(FacesContext facesContext, UIComponent uiComponent) throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();

        writer.endElement(HTML.INPUT_ELEM);
        
        UIForm form = ComponentUtils.closest(UIForm.class, uiComponent);
        if (form != null)
        {
            HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(form, facesContext, writer);
        }
    }

    protected String buildBehaviorizedOnClick(UIComponent uiComponent, Map<String, List<ClientBehavior>> behaviors, 
                                              FacesContext facesContext, ResponseWriter writer, 
                                              UIComponent form, List<UIParameter> validParams)
        throws IOException
    {
        StringBuilder sb = SharedStringBuilder.get(facesContext, SB_BUILD_BEHAVIORIZED_ONCLICK);
        
        //user onclick part 
        String commandOnClick = (String) uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);
        if (commandOnClick != null)
        {
            sb.append(commandOnClick);
            sb.append(';');
        }
        String userOnClick = sb.toString();

        // reset SB and reuse
        sb.setLength(0);

        if (form != null) 
        {
            // There is no clean way to detect if a "submit" behavior has been added to the component, 
            // so to keep things simple, if the button is submit type, it is responsibility of the 
            // developer to add a client behavior that submit the form, for example using a f:ajax tag.
            // Otherwise, there will be a situation where a full submit could be trigger after an ajax
            // operation. Note we still need to append two scripts if necessary: autoscroll and clear
            // hidden fields, because this code is called for a submit button.
            //if (behaviors.isEmpty() && validParams != null && !validParams.isEmpty() )
            //{
            //    rendererOnClick.append(buildServerOnclick(facesContext, uiComponent, 
            //            uiComponent.getClientId(facesContext), nestedFormInfo, validParams));
            //}
            //else
            //{
                if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
                {
                    //call the script to clear the form (clearFormHiddenParams_<formName>) method
                    HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(sb,
                            form.getClientId(facesContext));
                }
            //}
        }

        //according to the specification in jsf.util.chain jdocs and the spec document we have to use
        //jsf.util.chain to chain the functions and
        Collection<ClientBehaviorContext.Parameter> paramList = HtmlRendererUtils.getClientBehaviorContextParameters(
                HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, uiComponent));
        
        return HtmlRendererUtils.buildBehaviorChain(facesContext, uiComponent,
                ClientBehaviorEvents.CLICK, paramList, ClientBehaviorEvents.ACTION, paramList, behaviors,
                userOnClick , sb.toString());
    }

    private StringBuilder addChildParameters(FacesContext context, List<UIParameter> validParams)
    {
        //add child parameters
        StringBuilder params = SharedStringBuilder.get(context, SB_ADD_CHILD_PARAMETERS);
        params.append('[');
        
        for (int i = 0, size = validParams.size(); i < size; i++)
        {
            UIParameter param = validParams.get(i);
            String name = param.getName();
            Object value = param.getValue();

            //UIParameter is no ValueHolder, so no conversion possible - calling .toString on value....
            // MYFACES-1832 bad charset encoding for f:param
            // if HTMLEncoder.encode is called, then
            // when is called on writer.writeAttribute, encode method
            // is called again so we have a duplicated encode call.
            // MYFACES-2726 All '\' and "'" chars must be escaped 
            // because there will be inside "'" javascript quotes, 
            // otherwise the value will not correctly restored when
            // the command is post.
            //String strParamValue = value != null ? value.toString() : "";
            String strParamValue = "";
            if (value != null)
            {
                strParamValue = value.toString();
                StringBuilder buff = null;
                for (int j = 0; j < strParamValue.length(); j++)
                {
                    char c = strParamValue.charAt(j); 
                    if (c == '\'' || c == '\\')
                    {
                        if (buff == null)
                        {
                            buff = new StringBuilder();
                            buff.append(strParamValue.substring(0,j));
                        }
                        buff.append('\\');
                        buff.append(c);
                    }
                    else if (buff != null)
                    {
                        buff.append(c);
                    }
                }
                if (buff != null)
                {
                    strParamValue = buff.toString();
                }
            }

            if (params.length() > 1) 
            {
                params.append(',');
            }

            params.append("['");
            params.append(name);
            params.append("','");
            params.append(strParamValue);
            params.append("']");
        }
        params.append(']');
        return params;
    }

    private String getTarget(UIComponent component)
    {
        // for performance reason: double check for the target attribute
        String target;
        if (component instanceof HtmlCommandLink)
        {
            target = ((HtmlCommandLink) component).getTarget();
        }
        else
        {
            target = (String) component.getAttributes().get(HTML.TARGET_ATTR);
        }
        return target;
    }

    protected StringBuilder buildOnClick(UIComponent uiComponent, FacesContext facesContext,
                                        ResponseWriter writer, List<UIParameter> validParams)
        throws IOException
    {
        StringBuilder onClick = SharedStringBuilder.get(facesContext, SB_BUILD_ONCLICK);
        String commandOnClick = (String) uiComponent.getAttributes().get(HTML.ONCLICK_ATTR);

        if (commandOnClick != null)
        {
            onClick.append("var cf = function(){");
            onClick.append(commandOnClick);
            onClick.append('}');
            onClick.append(';');
            onClick.append("var oamSF = function(){");
        }

        UIForm form = ComponentUtils.closest(UIForm.class, uiComponent);        
        if (form != null)
        {
            if (validParams != null && !validParams.isEmpty() )
            {
                StringBuilder params = addChildParameters(facesContext, validParams);

                String target = getTarget(uiComponent);

                onClick.append("return ").
                    append(HtmlRendererUtils.SUBMIT_FORM_FN_NAME_JSF2).append("('").
                    append(form.getClientId(facesContext)).append("','").
                    append(uiComponent.getClientId(facesContext)).append('\'');

                if (params.length() > 2 || target != null)
                {
                    onClick.append(',').
                        append(target == null ? "null" : ('\'' + target + '\'')).append(',').
                        append(params);
                }
                onClick.append(");");
            }
            else
            {
        
                if (JavascriptUtils.isRenderClearJavascriptOnButton(facesContext.getExternalContext()))
                {
                    //call the script to clear the form (clearFormHiddenParams_<formName>) method
                    HtmlRendererUtils.appendClearHiddenCommandFormParamsFunctionCall(onClick,
                            form.getClientId(facesContext));
                }
            }
        }
        
        if (commandOnClick != null)
        {
            onClick.append('}');
            onClick.append(';');
            onClick.append("return (cf.apply(this, [])==false)? false : oamSF.apply(this, []); ");
        }  

        return onClick;
    }


    protected boolean isDisabled(FacesContext facesContext, UIComponent uiComponent)
    {
        if (uiComponent instanceof HtmlCommandButton)
        {
            return ((HtmlCommandButton) uiComponent).isDisabled();
        }

        return RendererUtils.getBooleanAttribute(uiComponent, HTML.DISABLED_ATTR, false);
    }

    protected boolean isReadonly(FacesContext facesContext, UIComponent uiComponent)
    {
        if (uiComponent instanceof HtmlCommandButton)
        {
            return ((HtmlCommandButton)uiComponent).isReadonly();
        }
        return RendererUtils.getBooleanAttribute(
                uiComponent, HTML.READONLY_ATTR, false);
    }

    private String getType(UIComponent uiComponent)
    {
        if (uiComponent instanceof HtmlCommandButton)
        {
            return ((HtmlCommandButton)uiComponent).getType();
        }
        return (String)uiComponent.getAttributes().get(JSFAttr.TYPE_ATTR);
    }

    private Object getValue(UIComponent uiComponent)
    {
        if (uiComponent instanceof ValueHolder)
        {
            return ((ValueHolder)uiComponent).getValue();
        }
        return uiComponent.getAttributes().get(JSFAttr.VALUE_ATTR);
    }
}
