// Copyright 2004, 2005 The Apache Software Foundation
//
// Licensed 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.tapestry.form;

import org.apache.hivemind.ApplicationRuntimeException;
import org.apache.hivemind.Location;
import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IActionListener;
import org.apache.tapestry.IComponent;
import org.apache.tapestry.IDirect;
import org.apache.tapestry.IForm;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRender;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.RenderRewoundException;
import org.apache.tapestry.Tapestry;
import org.apache.tapestry.TapestryUtils;
import org.apache.tapestry.engine.ActionServiceParameter;
import org.apache.tapestry.engine.DirectServiceParameter;
import org.apache.tapestry.engine.IEngineService;
import org.apache.tapestry.engine.ILink;
import org.apache.tapestry.listener.ListenerInvoker;
import org.apache.tapestry.valid.IValidationDelegate;
import org.apache.tapestry.web.WebResponse;

/**
 * Component which contains form element components. Forms use the action or direct services to
 * handle the form submission. A Form will wrap other components and static HTML, including form
 * components such as {@link TextArea}, {@link TextField}, {@link Checkbox}, etc. [ <a
 * href="../../../../../ComponentReference/Form.html">Component Reference </a>]
 * <p>
 * When a form is submitted, it continues through the rewind cycle until <em>after</em> all of its
 * wrapped elements have renderred. As the form component render (in the rewind cycle), they will be
 * updating properties of the containing page and notifying thier listeners. Again: each form
 * component is responsible not only for rendering HTML (to present the form), but for handling it's
 * share of the form submission.
 * <p>
 * Only after all that is done will the Form notify its listener.
 * <p>
 * Starting in release 1.0.2, a Form can use either the direct service or the action service. The
 * default is the direct service, even though in earlier releases, only the action service was
 * available.
 * <p>
 * Release 4.0 adds two new listeners, {@link #getCancel()} and {@link #getRefresh()} and
 * corresponding client-side behavior to force a form to refresh (update, bypassing input field
 * validation) or cancel (update immediately).
 * 
 * @author Howard Lewis Ship, David Solis
 */

public abstract class Form extends AbstractComponent implements IForm, IDirect
{
    private String _name;

    private FormSupport _formSupport;

    private class RenderInformalParameters implements IRender
    {
        public void render(IMarkupWriter writer, IRequestCycle cycle)
        {
            renderInformalParameters(writer, cycle);
        }
    }

    private IRender _renderInformalParameters;

    /**
     * Returns the currently active {@link IForm}, or null if no form is active. This is a
     * convienience method, the result will be null, or an instance of {@link IForm}, but not
     * necessarily a <code>Form</code>.
     * 
     * @deprecated Use {@link TapestryUtils#getForm(IRequestCycle, IComponent)} instead.
     */

    public static IForm get(IRequestCycle cycle)
    {
        return (IForm) cycle.getAttribute(ATTRIBUTE_NAME);
    }

    /**
     * Indicates to any wrapped form components that they should respond to the form submission.
     * 
     * @throws ApplicationRuntimeException
     *             if not rendering.
     */

    public boolean isRewinding()
    {
        if (!isRendering())
            throw Tapestry.createRenderOnlyPropertyException(this, "rewinding");

        return _formSupport.isRewinding();
    }

    /**
     * Injected.
     * 
     * @since 4.0
     */

    public abstract IEngineService getDirectService();

    /**
     * Injected.
     * 
     * @since 4.0
     */

    public abstract IEngineService getActionService();

    /**
     * Returns true if this Form is configured to use the direct service.
     * <p>
     * This is derived from the direct parameter, and defaults to true if not bound.
     * 
     * @since 1.0.2
     */

    public abstract boolean isDirect();

    /**
     * Returns true if the stateful parameter is bound to a true value. If stateful is not bound,
     * also returns the default, true.
     * 
     * @since 1.0.1
     */

    public boolean getRequiresSession()
    {
        return isStateful();
    }

    /**
     * Constructs a unique identifier (within the Form). The identifier consists of the component's
     * id, with an index number added to ensure uniqueness.
     * <p>
     * Simply invokes
     * {@link #getElementId(org.apache.tapestry.form.IFormComponent, java.lang.String)}with the
     * component's id.
     * 
     * @since 1.0.2
     */

    public String getElementId(IFormComponent component)
    {
        return _formSupport.getElementId(component, component.getId());
    }

    /**
     * Constructs a unique identifier from the base id. If possible, the id is used as-is.
     * Otherwise, a unique identifier is appended to the id.
     * <p>
     * This method is provided simply so that some components ({@link ImageSubmit}) have more
     * specific control over their names.
     * 
     * @since 1.0.3
     */

    public String getElementId(IFormComponent component, String baseId)
    {
        return _formSupport.getElementId(component, baseId);
    }

    /**
     * Returns the name generated for the form. This is used to faciliate components that write
     * JavaScript and need to access the form or its contents.
     * <p>
     * This value is generated when the form renders, and is not cleared. If the Form is inside a
     * {@link org.apache.tapestry.components.Foreach}, this will be the most recently generated
     * name for the Form.
     * <p>
     * This property is exposed so that sophisticated applications can write JavaScript handlers for
     * the form and components within the form.
     * 
     * @see AbstractFormComponent#getName()
     */

    public String getName()
    {
        return _name;
    }

    /** @since 3.0 * */

    protected void prepareForRender(IRequestCycle cycle)
    {
        super.prepareForRender(cycle);

        TapestryUtils.storeForm(cycle, this);
    }

    protected void cleanupAfterRender(IRequestCycle cycle)
    {
        _formSupport = null;

        TapestryUtils.removeForm(cycle);

        IValidationDelegate delegate = getDelegate();

        if (delegate != null)
            delegate.setFormComponent(null);

        super.cleanupAfterRender(cycle);
    }

    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle)
    {
        String actionId = cycle.getNextActionId();

        _formSupport = newFormSupport(writer, cycle);

        if (isRewinding())
        {
            String submitType = _formSupport.rewind();

            IActionListener listener = findListener(submitType);

            getListenerInvoker().invokeListener(listener, this, cycle);

            // Abort the rewind render.

            throw new RenderRewoundException(this);
        }

        // Note: not safe to invoke getNamespace() in Portlet world
        // except during a RenderRequest.

        String baseName = isDirect() ? constructFormNameForDirectService(cycle)
                : constructFormNameForActionService(actionId);

        _name = baseName + getResponse().getNamespace();

        if (_renderInformalParameters == null)
            _renderInformalParameters = new RenderInformalParameters();

        ILink link = getLink(cycle, actionId);
        
        _formSupport.render(getMethod(), _renderInformalParameters, link, getScheme(), getPort());
    }

    IActionListener findListener(String mode)
    {
        IActionListener result = null;

        if (mode.equals(FormConstants.SUBMIT_CANCEL))
            result = getCancel();
        else if (mode.equals(FormConstants.SUBMIT_REFRESH))
            result = getRefresh();
        else if (!getDelegate().getHasErrors())
            result = getSuccess();

        // If not success, cancel or refresh, or the corresponding listener
        // is itself null, then use the default listener
        // (which may be null as well!).

        if (result == null)
            result = getListener();

        return result;
    }

    /**
     * Construct a form name for use with the action service. This implementation returns "Form"
     * appended with the actionId.
     * 
     * @since 4.0
     */

    protected String constructFormNameForActionService(String actionId)
    {
        return "Form" + actionId;
    }

    /**
     * Constructs a form name for use with the direct service. This implementation bases the form
     * name on the form component's id (but ensures it is unique). Remember that Tapestry assigns an
     * "ugly" id if an explicit component id is not provided.
     * 
     * @since 4.0
     */

    private String constructFormNameForDirectService(IRequestCycle cycle)
    {
        return cycle.getUniqueId(TapestryUtils.convertTapestryIdToNMToken(getId()));
    }

    /**
     * Returns a new instance of {@link FormSupportImpl}.
     */

    protected FormSupport newFormSupport(IMarkupWriter writer, IRequestCycle cycle)
    {
        return new FormSupportImpl(writer, cycle, this);
    }

    /**
     * Adds an additional event handler.
     * 
     * @since 1.0.2
     */

    public void addEventHandler(FormEventType type, String functionName)
    {
        _formSupport.addEventHandler(type, functionName);
    }

    /**
     * Simply invokes {@link #render(IMarkupWriter, IRequestCycle)}.
     * 
     * @since 1.0.2
     */

    public void rewind(IMarkupWriter writer, IRequestCycle cycle)
    {
        render(writer, cycle);
    }

    /**
     * Method invoked by the direct service.
     * 
     * @since 1.0.2
     */

    public void trigger(IRequestCycle cycle)
    {
        cycle.rewindForm(this);
    }

    /**
     * Builds the EngineServiceLink for the form, using either the direct or action service.
     * 
     * @since 1.0.3
     */

    protected ILink getLink(IRequestCycle cycle, String actionId)
    {
        if (isDirect())
        {
            Object parameter = new DirectServiceParameter(this);
            return getDirectService().getLink(true, parameter);
        }

        // I'd love to pull out support for the action service entirely!

        Object parameter = new ActionServiceParameter(this, actionId);

        return getActionService().getLink(true, parameter);
    }

    /** Injected */

    public abstract WebResponse getResponse();

    /**
     * delegate parameter, which has a default (starting in release 4.0).
     */

    public abstract IValidationDelegate getDelegate();

    /** listener parameter, may be null */
    public abstract IActionListener getListener();

    /** success parameter, may be null */
    public abstract IActionListener getSuccess();

    /** cancel parameter, may be null */
    public abstract IActionListener getCancel();

    /** refresh parameter, may be null */
    public abstract IActionListener getRefresh();

    /** method parameter */
    public abstract String getMethod();

    /** stateful parameter */
    public abstract boolean isStateful();

    /** scheme parameter, may be null */
    public abstract String getScheme();
    
    /** port , may be null */
    public abstract Integer getPort();

    public void setEncodingType(String encodingType)
    {
        _formSupport.setEncodingType(encodingType);
    }

    /** @since 3.0 */

    public void addHiddenValue(String name, String value)
    {
        _formSupport.addHiddenValue(name, value);
    }

    /** @since 3.0 */

    public void addHiddenValue(String name, String id, String value)
    {
        _formSupport.addHiddenValue(name, id, value);
    }

    public void prerenderField(IMarkupWriter writer, IComponent field, Location location)
    {
        _formSupport.prerenderField(writer, field, location);
    }

    public boolean wasPrerendered(IMarkupWriter writer, IComponent field)
    {
        return _formSupport.wasPrerendered(writer, field);
    }

    /** @since 4.0 */

    public void addDeferredRunnable(Runnable runnable)
    {
        _formSupport.addDeferredRunnable(runnable);
    }

    /**
     * Injected
     * 
     * @since 4.0
     */

    public abstract ListenerInvoker getListenerInvoker();

    public void registerForFocus(IFormComponent field, int priority)
    {
        _formSupport.registerForFocus(field, priority);
    }

}
