/*
 * 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.HtmlRendererUtils;
import org.apache.myfaces.renderkit.html.util.ClientBehaviorRendererUtils;
import org.apache.myfaces.renderkit.html.util.CommonPropertyUtils;
import org.apache.myfaces.renderkit.html.util.CommonEventUtils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.RandomAccess;

import javax.faces.component.UICommand;
import javax.faces.component.UIComponent;
import javax.faces.component.UIForm;
import javax.faces.component.UIOutcomeTarget;
import javax.faces.component.UIOutput;
import javax.faces.component.UIParameter;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.component.behavior.ClientBehaviorHint;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.component.html.HtmlCommandLink;
import javax.faces.component.html.HtmlOutputLink;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.event.ActionEvent;

import org.apache.myfaces.config.MyfacesConfig;
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.ResourceUtils;
import org.apache.myfaces.renderkit.html.util.HTML;
import org.apache.myfaces.util.ComponentUtils;
import org.apache.myfaces.util.SharedStringBuilder;

public abstract class HtmlLinkRendererBase extends HtmlRenderer
{
    public static final String END_LINK_OUTCOME_AS_SPAN = 
        "oam.shared.HtmlLinkRendererBase.END_LINK_OUTCOME_AS_SPAN";

    private static final String SB_BUILD_ONCLICK = HtmlLinkRendererBase.class.getName()
            + "#buildOnClick";
    private static final String SB_ADD_CHILD_PARAMETERS = HtmlLinkRendererBase.class.getName() +
            "#addChildParameters";

    private MyfacesConfig myfacesConfig;
    
    public HtmlLinkRendererBase()
    {
        myfacesConfig = MyfacesConfig.getCurrentInstance();
    }
    
    @Override
    public boolean getRendersChildren()
    {
        // We must be able to render the children without a surrounding anchor
        // if the Link is disabled
        return true;
    }

    @Override
    public void decode(FacesContext facesContext, UIComponent component)
    {
        super.decode(facesContext, component);  //check for NP

        if (component instanceof UICommand)
        {
            String clientId = component.getClientId(facesContext);
            UIForm form = ComponentUtils.closest(UIForm.class, component);
            boolean disabled = HtmlRendererUtils.isDisabled(component);
            // MYFACES-3960 Decode, decode client behavior and queue action event at the end
            boolean activateActionEvent = false;
            if (form != null && !disabled)
            {
                String reqValue = (String) facesContext.getExternalContext().getRequestParameterMap().get(
                        HtmlRendererUtils.getHiddenCommandLinkFieldName(form, facesContext));
                activateActionEvent = reqValue != null && reqValue.equals(clientId)
                    || HtmlRendererUtils.isPartialOrBehaviorSubmit(facesContext, clientId);
            }
            if (component instanceof ClientBehaviorHolder && !disabled)
            {
                ClientBehaviorRendererUtils.decodeClientBehaviors(facesContext, component);
            }
            if (activateActionEvent)
            {
                component.queueEvent(new ActionEvent(component));
            }
        }
        else if (component instanceof UIOutput)
        {
            //do nothing
            if (component instanceof ClientBehaviorHolder && !HtmlRendererUtils.isDisabled(component))
            {
                ClientBehaviorRendererUtils.decodeClientBehaviors(facesContext, component);
            }
        }
        else
        {
            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
        }
    }

    @Override
    public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException
    {
        super.encodeBegin(facesContext, component);  //check for NP

        if (component instanceof ClientBehaviorHolder)
        {
            Map<String, List<ClientBehavior>> behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
            if (!behaviors.isEmpty())
            {
                ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());
            }
        }
        
        if (component instanceof UICommand)
        {
            renderCommandLinkStart(facesContext, component,
                                   component.getClientId(facesContext),
                                   ((UICommand) component).getValue(),
                                   getStyle(facesContext, component),
                                   getStyleClass(facesContext, component));
        }
        else if (component instanceof UIOutcomeTarget)
        {
            renderOutcomeLinkStart(facesContext, (UIOutcomeTarget)component);
        }        
        else if (component instanceof UIOutput)
        {
            renderOutputLinkStart(facesContext, (UIOutput)component);
        }
        else
        {
            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
        }
    }


    /**
     * Can be overwritten by derived classes to overrule the style to be used.
     */
    protected String getStyle(FacesContext facesContext, UIComponent link)
    {
        if (link instanceof HtmlCommandLink)
        {
            return ((HtmlCommandLink)link).getStyle();
        }

        return (String)link.getAttributes().get(HTML.STYLE_ATTR);

    }

    /**
     * Can be overwritten by derived classes to overrule the style class to be used.
     */
    protected String getStyleClass(FacesContext facesContext, UIComponent link)
    {
        if (link instanceof HtmlCommandLink)
        {
            return ((HtmlCommandLink)link).getStyleClass();
        }

        return (String)link.getAttributes().get(HTML.STYLE_CLASS_ATTR);

    }

    @Override
    public void encodeChildren(FacesContext facesContext, UIComponent component) throws IOException
    {
        RendererUtils.renderChildren(facesContext, component);
    }

    @Override
    public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException
    {
        super.encodeEnd(facesContext, component);  //check for NP

        if (component instanceof UICommand)
        {
            renderCommandLinkEnd(facesContext, component);

            UIForm form = ComponentUtils.closest(UIForm.class, component);
            if (form != null)
            {
                HtmlFormRendererBase.renderScrollHiddenInputIfNecessary(
                        form, facesContext, facesContext.getResponseWriter());
            }
        }
        else if (component instanceof UIOutcomeTarget)
        {
            renderOutcomeLinkEnd(facesContext, component);
        }
        else if (component instanceof UIOutput)
        {
            renderOutputLinkEnd(facesContext, component);
        }
        else
        {
            throw new IllegalArgumentException("Unsupported component class " + component.getClass().getName());
        }
    }

    protected void renderCommandLinkStart(FacesContext facesContext, UIComponent component,
                                          String clientId,
                                          Object value,
                                          String style,
                                          String styleClass)
            throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();
        Map<String, List<ClientBehavior>> behaviors = null;

        // h:commandLink can be rendered outside a form, but with warning (jsf 2.0 TCK)
        UIForm form = ComponentUtils.closest(UIForm.class, component);
        
        boolean disabled = HtmlRendererUtils.isDisabled(component);
        
        if (disabled || form == null)
        {
            writer.startElement(HTML.SPAN_ELEM, component);
            if (component instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
                }
                else
                {
                    HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
                }
                
                // only render onclick if != disabled
                if (!disabled)
                {
                    if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                    {
                        CommonPropertyUtils.renderEventProperties(writer, 
                                commonPropertiesMarked, component);
                        CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                                commonPropertiesMarked, component);
                    }
                    else
                    {
                        if (isCommonEventsOptimizationEnabled(facesContext))
                        {
                            Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(component);
                            CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
                                    commonPropertiesMarked, commonEventsMarked, component, behaviors);
                            CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, commonPropertiesMarked, commonEventsMarked, component, behaviors);
                        }
                        else
                        {
                            HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, component, 
                                    behaviors);
                            HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                    facesContext, writer, component, behaviors);
                        }
                    }
                }
                else
                {
                    if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                    {
                        CommonPropertyUtils.renderEventPropertiesWithoutOnclick(writer, 
                                commonPropertiesMarked, component);
                        CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                                commonPropertiesMarked, component);
                    }
                    else
                    {
                        if (isCommonEventsOptimizationEnabled(facesContext))
                        {
                            Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(component);
                            CommonEventUtils.renderBehaviorizedEventHandlersWithoutOnclick(facesContext, writer, 
                                    commonPropertiesMarked, commonEventsMarked, component, behaviors);
                            CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, commonPropertiesMarked, commonEventsMarked, component, behaviors);
                        }
                        else
                        {
                            HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(facesContext, writer,
                                    component, behaviors);
                            HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                    facesContext, writer, component, behaviors);
                        }
                    }
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabledWithoutEvents(writer, 
                            commonPropertiesMarked, component);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED_WITHOUT_EVENTS);
                }
            }
            else
            {
                HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabled(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(component), component);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED);
                }
            }
        }
        else
        {
            if (component instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) component).getClientBehaviors();
                renderBehaviorizedJavaScriptAnchorStart(
                        facesContext, writer, component, clientId, behaviors, form);
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
                }
                else 
                {
                    // If onclick is not null, both onclick and server side script are rendered 
                    // using jsf.util.chain(...) js function. We need to check that case and force
                    // id/name rendering. It is possible to do something else in that case and 
                    // do not render the script using jsf.util.chain, but for now it is ok.
                    String commandOnclick;
                    if (component instanceof HtmlCommandLink)
                    {
                        commandOnclick = ((HtmlCommandLink)component).getOnclick();
                    }
                    else
                    {
                        commandOnclick = (String)component.getAttributes().get(HTML.ONCLICK_ATTR);
                    }

                    if (commandOnclick != null)
                    {
                        HtmlRendererUtils.writeIdAndName(writer, component, facesContext);
                    }
                    else
                    {
                        HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                    }
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(component);
                }
                if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderEventPropertiesWithoutOnclick(writer,
                        commonPropertiesMarked, component);
                    CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                            commonPropertiesMarked, component);
                }
                else
                {
                    HtmlRendererUtils.renderBehaviorizedEventHandlersWithoutOnclick(
                            facesContext, writer, component, behaviors);
                    HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                            facesContext, writer, component, behaviors);
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutStyleAndEvents(writer, 
                            commonPropertiesMarked, component);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_STYLE_AND_EVENTS);
                }
            }
            else
            {
                renderJavaScriptAnchorStart(facesContext, writer, component, clientId, form);
                HtmlRendererUtils.writeIdIfNecessary(writer, component, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutOnclickAndStyle(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(component), component);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, component, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_ONCLICK_WITHOUT_STYLE);
                }
            }

            HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_ATTR, HTML.STYLE_ATTR, style);
            HtmlRendererUtils.renderHTMLAttribute(writer, HTML.STYLE_CLASS_ATTR, HTML.STYLE_CLASS_ATTR, styleClass);
        }

        // render value as required by JSF 1.1 renderkitdocs
        if(value != null)
        {
            writer.writeText(value.toString(), JSFAttr.VALUE_ATTR);
        }
        
        // render warning message for a h:commandLink with no nesting form
        if (form == null)
        {
            writer.writeText(": This link is deactivated, because it is not embedded in a JSF form.", null);
        }
    }

    protected void renderJavaScriptAnchorStart(FacesContext facesContext,
                                               ResponseWriter writer,
                                               UIComponent component,
                                               String clientId,
                                               UIComponent form)
        throws IOException
    {
        StringBuilder onClick = SharedStringBuilder.get(facesContext, SB_BUILD_ONCLICK);

        String commandOnclick;
        if (component instanceof HtmlCommandLink)
        {
            commandOnclick = ((HtmlCommandLink)component).getOnclick();
        }
        else
        {
            commandOnclick = (String)component.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(){");
        }

        StringBuilder params = addChildParameters(facesContext, component, form);

        String target = getTarget(component);

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

        if (params.length() > 2 || target != null)
        {
            onClick.append(',').
                append(target == null ? "null" : ('\'' + target + '\'')).append(',').
                append(params);
        }
        onClick.append(");");

        
        if (commandOnclick != null)
        {
            onClick.append('}');
            onClick.append(';');
            onClick.append("return (cf.apply(this, [])==false)? false : oamSF.apply(this, []); ");
        }        

        writer.startElement(HTML.ANCHOR_ELEM, component);
        writer.writeURIAttribute(HTML.HREF_ATTR, "#", null);
        writer.writeAttribute(HTML.ONCLICK_ATTR, onClick.toString(), null);
    }

    
    protected void renderBehaviorizedJavaScriptAnchorStart(FacesContext facesContext,
            ResponseWriter writer,
            UIComponent component,
            String clientId,
            Map<String, List<ClientBehavior>> behaviors,
            UIComponent formInfo) throws IOException
    {
        String commandOnclick;
        if (component instanceof HtmlCommandLink)
        {
            commandOnclick = ((HtmlCommandLink)component).getOnclick();
        }
        else
        {
            commandOnclick = (String)component.getAttributes().get(HTML.ONCLICK_ATTR);
        }

        //Calculate the script necessary to submit form
        String serverEventCode = buildServerOnclick(facesContext, component, clientId, formInfo);
        
        String onclick = null;
        
        if (commandOnclick == null && (behaviors.isEmpty() || 
            (!behaviors.containsKey(ClientBehaviorEvents.CLICK) && 
             !behaviors.containsKey(ClientBehaviorEvents.ACTION) ) ) )
        {
            //we need to render only the submit script
            onclick = serverEventCode;
        }
        else
        {
            boolean hasSubmittingBehavior = hasSubmittingBehavior(behaviors, ClientBehaviorEvents.CLICK)
                || hasSubmittingBehavior(behaviors, ClientBehaviorEvents.ACTION);
            if (!hasSubmittingBehavior)
            {
                //Ensure required resource javascript is available
                ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, writer);
            }
            
            //render a javascript that chain the related code
            Collection<ClientBehaviorContext.Parameter> paramList = 
                ClientBehaviorRendererUtils.getClientBehaviorContextParameters(
                    HtmlRendererUtils.mapAttachedParamsToStringValues(facesContext, component));
            
            onclick = ClientBehaviorRendererUtils.buildBehaviorChain(facesContext, component,
                    ClientBehaviorEvents.CLICK, paramList, ClientBehaviorEvents.ACTION, paramList, behaviors,
                    commandOnclick , hasSubmittingBehavior ? null : serverEventCode);
        }
        
        writer.startElement(HTML.ANCHOR_ELEM, component);
        writer.writeURIAttribute(HTML.HREF_ATTR, "#", null);
        writer.writeAttribute(HTML.ONCLICK_ATTR, onclick, null);
    }

    private boolean hasSubmittingBehavior(Map<String, List<ClientBehavior>> clientBehaviors, String eventName)
    {
        List<ClientBehavior> eventBehaviors = clientBehaviors.get(eventName);
        if (eventBehaviors != null && !eventBehaviors.isEmpty())
        {
            // perf: in 99% cases is  eventBehaviors javax.faces.component._DeltaList._DeltaList(int) = RandomAccess
            // instance created in javax.faces.component.UIComponentBase.addClientBehavior(String, ClientBehavior), but
            // component libraries can provide own implementation
            if (eventBehaviors instanceof RandomAccess)
            {
                for (int i = 0, size = eventBehaviors.size(); i < size; i++)
                {
                    ClientBehavior behavior = eventBehaviors.get(i);
                    if (behavior.getHints().contains(ClientBehaviorHint.SUBMITTING))
                    {
                        return true;
                    }
                }
            }
            else
            {
                for (ClientBehavior behavior : eventBehaviors)
                {
                    if (behavior.getHints().contains(ClientBehaviorHint.SUBMITTING))
                    {
                        return true;
                    }
                }
            }
        }
        return false;
    }

    protected String buildServerOnclick(FacesContext facesContext, UIComponent component, 
            String clientId, UIComponent form) throws IOException
    {
        ResourceUtils.renderDefaultJsfJsInlineIfNecessary(facesContext, facesContext.getResponseWriter());

        StringBuilder onClick = SharedStringBuilder.get(facesContext, SB_BUILD_ONCLICK);

        StringBuilder params = addChildParameters(facesContext, component, form);

        String target = getTarget(component);

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

        if (params.length() > 2 || target != null)
        {
            onClick.append(',').
                append(target == null ? "null" : ('\'' + target + '\'')).append(',').
                append(params);
        }
        onClick.append(");");
        
        return onClick.toString();
    }

    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;
    }

    private StringBuilder addChildParameters(FacesContext context, UIComponent component, UIComponent nestingForm)
    {
        //add child parameters
        StringBuilder params = SharedStringBuilder.get(context, SB_ADD_CHILD_PARAMETERS);
        params.append('[');

        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
                context, getChildren(component), false, false);
        for (int j = 0, size = validParams.size(); j < size; j++) 
        {
            UIParameter param = validParams.get(j);
            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 i = 0; i < strParamValue.length(); i++)
                {
                    char c = strParamValue.charAt(i); 
                    if (c == '\'' || c == '\\')
                    {
                        if (buff == null)
                        {
                            buff = new StringBuilder();
                            buff.append(strParamValue.substring(0,i));
                        }
                        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 void addChildParametersToHref(FacesContext facesContext,
                                          UIComponent linkComponent,
                                          StringBuilder hrefBuf,
                                          boolean firstParameter,
                                          String charEncoding)
            throws IOException
    {
        List<UIParameter> validParams = HtmlRendererUtils.getValidUIParameterChildren(
                facesContext, getChildren(linkComponent), false, false);
        
        for (int i = 0, size = validParams.size(); i < size; i++)
        {
            UIParameter param = validParams.get(i);
            String name = param.getName();
            Object value = param.getValue();
            addParameterToHref(name, value, hrefBuf, firstParameter, charEncoding, myfacesConfig.isStrictXhtmlLinks());
            firstParameter = false;
        }
    }

    protected void renderOutputLinkStart(FacesContext facesContext, UIOutput output)
            throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();
        Map<String, List<ClientBehavior>> behaviors = null;

        if (HtmlRendererUtils.isDisabled(output))
        {
            writer.startElement(HTML.SPAN_ELEM, output);
            if (output instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, output, facesContext);
                }
                else
                {
                    HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(output);
                }

                if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderEventProperties(writer, 
                            commonPropertiesMarked, output);
                    CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                            commonPropertiesMarked, output);
                }
                else
                {
                    if (isCommonEventsOptimizationEnabled(facesContext))
                    {
                        Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(output);
                        CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
                                commonPropertiesMarked, commonEventsMarked, output, behaviors);
                        CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                            facesContext, writer, commonPropertiesMarked, commonEventsMarked, output, behaviors);
                    }
                    else
                    {
                        HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
                        HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, output, behaviors);
                    }
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabledWithoutEvents(writer, 
                            commonPropertiesMarked, output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED_WITHOUT_EVENTS);
                }
            }
            else
            {
                HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabled(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(output), output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED);
                }
            }
        }
        else
        { 
            //calculate href
            String href = RendererUtils.getStringValue(facesContext, output);
            
            //check if there is an anchor # in it
            int index = href.indexOf('#');
            String anchorString = null;
            boolean isAnchorInHref = (index > -1);
            if (isAnchorInHref)
            {
                // remove anchor element and add it again after the parameter are encoded
                anchorString = href.substring(index,href.length());
                href = href.substring(0,index);
            }
            if (getChildCount(output) > 0)
            {
                StringBuilder hrefBuf = new StringBuilder(href);
                addChildParametersToHref(facesContext, output, hrefBuf,
                                     (href.indexOf('?') == -1), //first url parameter?
                                     writer.getCharacterEncoding());
                href = hrefBuf.toString();
            }
            // check for the fragement attribute
            String fragmentAttr = null;
            if (output instanceof HtmlOutputLink)
            {
                fragmentAttr = ((HtmlOutputLink) output).getFragment();
            }
            else
            {
                fragmentAttr = (String) output.getAttributes().get(JSFAttr.FRAGMENT_ATTR);
            }
            if (fragmentAttr != null && !fragmentAttr.isEmpty())
            {
                href += '#' + fragmentAttr;
            }
            else if (isAnchorInHref)
            {
                href += anchorString;
            }
            href = facesContext.getExternalContext().encodeResourceURL(href);    //TODO: or encodeActionURL ?

            //write anchor
            writer.startElement(HTML.ANCHOR_ELEM, output);
            writer.writeURIAttribute(HTML.HREF_ATTR, href, null);
            if (output instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, output, facesContext);
                }
                else
                {
                    HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(output);
                }
                if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderEventProperties(writer, 
                            commonPropertiesMarked, output);
                    CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                            commonPropertiesMarked, output);
                }
                else
                {
                    if (isCommonEventsOptimizationEnabled(facesContext))
                    {
                        Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(output);
                        CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
                                commonPropertiesMarked, commonEventsMarked, output, behaviors);
                        CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                            facesContext, writer, commonPropertiesMarked, commonEventsMarked, output, behaviors);
                    }
                    else
                    {
                        HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
                        HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, output, behaviors);
                    }
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
                            commonPropertiesMarked, output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                }
            }
            else
            {
                HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughProperties(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(output), output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
                }
            }
            writer.flush();
        }
    }
    
    protected void renderOutcomeLinkStart(FacesContext facesContext, UIOutcomeTarget output)
            throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();
        Map<String, List<ClientBehavior>> behaviors = null;
        
        //calculate href
        String targetHref = HtmlRendererUtils.getOutcomeTargetHref(facesContext, output);
        
        if (HtmlRendererUtils.isDisabled(output) || targetHref == null)
        {
            //output.getAttributes().put(END_LINK_OUTCOME_AS_SPAN, Boolean.TRUE);
            //Note one h:link cannot have a nested h:link as a child, so it is safe
            //to just put this flag on FacesContext attribute map
            facesContext.getAttributes().put(END_LINK_OUTCOME_AS_SPAN, Boolean.TRUE);
            writer.startElement(HTML.SPAN_ELEM, output);
            if (output instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, output, facesContext);
                }
                else
                {
                    HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(output);
                }
                if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderEventProperties(writer, 
                            commonPropertiesMarked, output);
                    CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                            commonPropertiesMarked, output);
                }
                else
                {
                    if (isCommonEventsOptimizationEnabled(facesContext))
                    {
                        Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(output);
                        CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
                                commonPropertiesMarked, commonEventsMarked, output, behaviors);
                        CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                            facesContext, writer, commonPropertiesMarked, commonEventsMarked, output, behaviors);
                    }
                    else
                    {
                        HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
                        HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, output, behaviors);
                    }
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabledWithoutEvents(writer, 
                            commonPropertiesMarked, output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED_WITHOUT_EVENTS);
                }
            }
            else
            {
                HtmlRendererUtils.writeIdIfNecessary(writer, output, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesDisabled(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(output), output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_DISABLED);
                }
            }

            Object value = output.getValue();

            if(value != null)
            {
                writer.writeText(value.toString(), JSFAttr.VALUE_ATTR);
            }
        }
        else
        {
            //write anchor
            writer.startElement(HTML.ANCHOR_ELEM, output);
            writer.writeURIAttribute(HTML.HREF_ATTR, targetHref, null);
            if (output instanceof ClientBehaviorHolder)
            {
                behaviors = ((ClientBehaviorHolder) output).getClientBehaviors();
                if (!behaviors.isEmpty())
                {
                    HtmlRendererUtils.writeIdAndName(writer, output, facesContext);
                }
                else
                {
                    HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                }
                long commonPropertiesMarked = 0L;
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    commonPropertiesMarked = CommonPropertyUtils.getCommonPropertiesMarked(output);
                }
                if (behaviors.isEmpty() && isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderEventProperties(writer, 
                            commonPropertiesMarked, output);
                    CommonPropertyUtils.renderFocusBlurEventProperties(writer,
                            commonPropertiesMarked, output);
                }
                else
                {
                    if (isCommonEventsOptimizationEnabled(facesContext))
                    {
                        Long commonEventsMarked = CommonEventUtils.getCommonEventsMarked(output);
                        CommonEventUtils.renderBehaviorizedEventHandlers(facesContext, writer, 
                                commonPropertiesMarked, commonEventsMarked, output, behaviors);
                        CommonEventUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                            facesContext, writer, commonPropertiesMarked, commonEventsMarked, output, behaviors);
                    }
                    else
                    {
                        HtmlRendererUtils.renderBehaviorizedEventHandlers(facesContext, writer, output, behaviors);
                        HtmlRendererUtils.renderBehaviorizedFieldEventHandlersWithoutOnchangeAndOnselect(
                                facesContext, writer, output, behaviors);
                    }
                }
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughPropertiesWithoutEvents(writer, 
                            commonPropertiesMarked, output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES_WITHOUT_EVENTS);
                }
            }
            else
            {
                HtmlRendererUtils.writeIdAndNameIfNecessary(writer, output, facesContext);
                if (isCommonPropertiesOptimizationEnabled(facesContext))
                {
                    CommonPropertyUtils.renderAnchorPassthroughProperties(writer, 
                            CommonPropertyUtils.getCommonPropertiesMarked(output), output);
                }
                else
                {
                    HtmlRendererUtils.renderHTMLAttributes(writer, output, 
                            HTML.ANCHOR_PASSTHROUGH_ATTRIBUTES);
                }
            }

            writer.flush();
        }
    }

    private static void addParameterToHref(String name,
                                           Object value,
                                           StringBuilder hrefBuf,
                                           boolean firstParameter,
                                           String charEncoding,
                                           boolean strictXhtmlLinks) throws UnsupportedEncodingException
    {
        if (name == null)
        {
            throw new IllegalArgumentException("Unnamed parameter value not allowed within command link.");
        }

        if (firstParameter)
        {
            hrefBuf.append('?');
        }
        else
        {
            if (strictXhtmlLinks)
            {
                hrefBuf.append("&amp;");
            }
            else
            {
                hrefBuf.append('&');
            }
        }

        hrefBuf.append(URLEncoder.encode(name, charEncoding));
        hrefBuf.append('=');
        if (value != null)
        {
            //UIParameter is no ConvertibleValueHolder, so no conversion possible
            hrefBuf.append(URLEncoder.encode(value.toString(), charEncoding));
        }
    }

    protected void renderOutcomeLinkEnd(FacesContext facesContext, UIComponent component)
            throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();
        
        if (HtmlRendererUtils.isDisabled(component) || Boolean.TRUE.equals(
                facesContext.getAttributes().get(END_LINK_OUTCOME_AS_SPAN)))
        {
            writer.endElement(HTML.SPAN_ELEM);
            facesContext.getAttributes().put(END_LINK_OUTCOME_AS_SPAN, Boolean.FALSE);
        }
        else
        {
            writer.writeText (RendererUtils.getStringValue(facesContext, component), null);
            writer.endElement(HTML.ANCHOR_ELEM);
        }
    }
    
    protected void renderOutputLinkEnd(FacesContext facesContext, UIComponent component)
            throws IOException
    {
        ResponseWriter writer = facesContext.getResponseWriter();

        if (HtmlRendererUtils.isDisabled(component))
        {
            writer.endElement(HTML.SPAN_ELEM);
        }
        else
        {
            // force separate end tag
            writer.writeText("", null);
            writer.endElement(HTML.ANCHOR_ELEM);
        }
    }

    protected void renderCommandLinkEnd(FacesContext facesContext, UIComponent component)
            throws IOException
    {
        UIForm form = ComponentUtils.closest(UIForm.class, component);
        
        ResponseWriter writer = facesContext.getResponseWriter();
        if (HtmlRendererUtils.isDisabled(component) || form == null)
        {
            writer.endElement(HTML.SPAN_ELEM);
        }
        else
        {
            writer.writeText("", null);
            writer.endElement(HTML.ANCHOR_ELEM);
        }
    }
}
