/*
 * Copyright 2008 Google Inc.
 *
 * 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 com.google.gwt.user.client.ui;

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.Scheduler;
import com.google.gwt.core.client.Scheduler.ScheduledCommand;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.FormElement;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.safehtml.client.SafeHtmlTemplates;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.safehtml.shared.SafeUri;
import com.google.gwt.safehtml.shared.annotations.IsSafeUri;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.impl.FormPanelImpl;
import com.google.gwt.user.client.ui.impl.FormPanelImplHost;

/**
 * A panel that wraps its contents in an HTML &lt;FORM&gt; element.
 *
 * <p>
 * This panel can be used to achieve interoperability with servers that accept
 * traditional HTML form encoding. The following widgets (those that implement
 * {@link com.google.gwt.user.client.ui.HasName}) will be submitted to the
 * server if they are contained within this panel:
 * <ul>
 * <li>{@link com.google.gwt.user.client.ui.TextBox}</li>
 * <li>{@link com.google.gwt.user.client.ui.PasswordTextBox}</li>
 * <li>{@link com.google.gwt.user.client.ui.RadioButton}</li>
 * <li>{@link com.google.gwt.user.client.ui.SimpleRadioButton}</li>
 * <li>{@link com.google.gwt.user.client.ui.CheckBox}</li>
 * <li>{@link com.google.gwt.user.client.ui.SimpleCheckBox}</li>
 * <li>{@link com.google.gwt.user.client.ui.TextArea}</li>
 * <li>{@link com.google.gwt.user.client.ui.ListBox}</li>
 * <li>{@link com.google.gwt.user.client.ui.FileUpload}</li>
 * <li>{@link com.google.gwt.user.client.ui.Hidden}</li>
 * </ul>
 * In particular, {@link com.google.gwt.user.client.ui.FileUpload} is
 * <i>only</i> useful when used within a FormPanel, because the browser will
 * only upload files using form submission.
 * </p>
 *
 * <p>
 * <h3>Example</h3>
 * {@example com.google.gwt.examples.FormPanelExample}
 * </p>
 */
@SuppressWarnings("deprecation")
public class FormPanel extends SimplePanel implements FiresFormEvents, FormPanelImplHost {
  /**
   * Fired when a form has been submitted successfully.
   */
  public static class SubmitCompleteEvent extends GwtEvent<SubmitCompleteHandler> {
    /**
     * The event type.
     */
    private static Type<SubmitCompleteHandler> TYPE;

    /**
     * Handler hook.
     *
     * @return the handler hook
     */
    public static Type<SubmitCompleteHandler> getType() {
      if (TYPE == null) {
        TYPE = new Type<SubmitCompleteHandler>();
      }
      return TYPE;
    }

    private String resultHtml;

    /**
     * Create a submit complete event.
     *
     * @param resultsHtml the results from submitting the form
     */
    protected SubmitCompleteEvent(String resultsHtml) {
      this.resultHtml = resultsHtml;
    }

    @Override
    public final Type<SubmitCompleteHandler> getAssociatedType() {
      return getType();
    }

    /**
     * Gets the result text of the form submission.
     *
     * @return the result html, or <code>null</code> if there was an error
     *         reading it
     * @tip The result html can be <code>null</code> as a result of submitting a
     *      form to a different domain.
     */
    public String getResults() {
      return resultHtml;
    }

    @Override
    protected void dispatch(SubmitCompleteHandler handler) {
      handler.onSubmitComplete(this);
    }
  }

  /**
   * Handler for {@link FormPanel.SubmitCompleteEvent} events.
   */
  public interface SubmitCompleteHandler extends EventHandler {
    /**
     * Fired when a form has been submitted successfully.
     *
     * @param event the event
     */
    void onSubmitComplete(FormPanel.SubmitCompleteEvent event);
  }

  /**
   * Fired when the form is submitted.
   */
  public static class SubmitEvent extends GwtEvent<SubmitHandler> {
    /**
     * The event type.
     */
    private static Type<SubmitHandler> TYPE;

    /**
     * Handler hook.
     *
     * @return the handler hook
     */
    public static Type<SubmitHandler> getType() {
      if (TYPE == null) {
        TYPE = new Type<SubmitHandler>();
      }
      return TYPE;
    }

    private boolean canceled = false;

    /**
     * Cancel the form submit. Firing this will prevent a subsequent
     * {@link FormPanel.SubmitCompleteEvent} from being fired.
     */
    public void cancel() {
      this.canceled = true;
    }

    @Override
    public final Type<FormPanel.SubmitHandler> getAssociatedType() {
      return getType();
    }

    /**
     * Gets whether this form submit will be canceled.
     *
     * @return <code>true</code> if the form submit will be canceled
     */
    public boolean isCanceled() {
      return canceled;
    }

    @Override
    protected void dispatch(FormPanel.SubmitHandler handler) {
      handler.onSubmit(this);
    }

    /**
     * This method is used for legacy support and should be removed when
     * {@link FormHandler} is removed.
     *
     * @deprecated Use {@link FormPanel.SubmitEvent#cancel()} instead
     */
    @Deprecated
    void setCanceled(boolean canceled) {
      this.canceled = canceled;
    }
  }

  /**
   * Handler for {@link FormPanel.SubmitEvent} events.
   */
  public interface SubmitHandler extends EventHandler {
    /**
     * Fired when the form is submitted.
     *
     * <p>
     * The FormPanel must <em>not</em> be detached (i.e. removed from its parent
     * or otherwise disconnected from a {@link RootPanel}) until the submission
     * is complete. Otherwise, notification of submission will fail.
     * </p>
     *
     * @param event the event
     */
    void onSubmit(FormPanel.SubmitEvent event);
  }

  interface IFrameTemplate extends SafeHtmlTemplates {
    static final IFrameTemplate INSTANCE = GWT.create(IFrameTemplate.class);

    @Template("<iframe src=\"about:blank\" name='{0}' tabindex='-1' "
        + "style='position:absolute;width:0;height:0;border:0'>")
    SafeHtml get(String name);
  }

  /**
   * Used with {@link #setEncoding(String)} to specify that the form will be
   * submitted using MIME encoding (necessary for {@link FileUpload} to work
   * properly).
   */
  public static final String ENCODING_MULTIPART = "multipart/form-data";

  /**
   * Used with {@link #setEncoding(String)} to specify that the form will be
   * submitted using traditional URL encoding.
   */
  public static final String ENCODING_URLENCODED = "application/x-www-form-urlencoded";

  /**
   * Used with {@link #setMethod(String)} to specify that the form will be
   * submitted using an HTTP GET request.
   */
  public static final String METHOD_GET = "get";

  /**
   * Used with {@link #setMethod(String)} to specify that the form will be
   * submitted using an HTTP POST request (necessary for {@link FileUpload} to
   * work properly).
   */
  public static final String METHOD_POST = "post";

  private static int formId = 0;
  private static FormPanelImpl impl = GWT.create(FormPanelImpl.class);

  /**
   * Creates a FormPanel that wraps an existing &lt;form&gt; element.
   *
   * This element must already be attached to the document. If the element is
   * removed from the document, you must call
   * {@link RootPanel#detachNow(Widget)}.
   *
   * <p>
   * The specified form element's target attribute will not be set, and the
   * {@link FormSubmitCompleteEvent} will not be fired.
   * </p>
   *
   * @param element the element to be wrapped
   */
  public static FormPanel wrap(Element element) {
    // Assert that the element is attached.
    assert Document.get().getBody().isOrHasChild(element);

    FormPanel formPanel = new FormPanel(element);

    // Mark it attached and remember it for cleanup.
    formPanel.onAttach();
    RootPanel.detachOnWindowClose(formPanel);

    return formPanel;
  }

  /**
   * Creates a FormPanel that wraps an existing &lt;form&gt; element.
   *
   * This element must already be attached to the document. If the element is
   * removed from the document, you must call
   * {@link RootPanel#detachNow(Widget)}.
   *
   * <p>
   * If the createIFrame parameter is set to <code>true</code>, then the wrapped
   * form's target attribute will be set to a hidden iframe. If not, the form's
   * target will be left alone, and the FormSubmitComplete event will not be
   * fired.
   * </p>
   *
   * @param element the element to be wrapped
   * @param createIFrame <code>true</code> to create an &lt;iframe&gt; element
   *          that will be targeted by this form
   */
  public static FormPanel wrap(Element element, boolean createIFrame) {
    // Assert that the element is attached.
    assert Document.get().getBody().isOrHasChild(element);

    FormPanel formPanel = new FormPanel(element, createIFrame);

    // Mark it attached and remember it for cleanup.
    formPanel.onAttach();
    RootPanel.detachOnWindowClose(formPanel);

    return formPanel;
  }

  private String frameName;
  private Element synthesizedFrame;

  /**
   * Creates a new FormPanel. When created using this constructor, it will be
   * submitted to a hidden &lt;iframe&gt; element, and the results of the
   * submission made available via {@link SubmitCompleteHandler}.
   *
   * <p>
   * The back-end server is expected to respond with a content-type of
   * 'text/html', meaning that the text returned will be treated as HTML. If any
   * other content-type is specified by the server, then the result HTML sent in
   * the onFormSubmit event will be unpredictable across browsers, and the
   * {@link SubmitCompleteHandler#onSubmitComplete(com.google.gwt.user.client.ui.FormPanel.SubmitCompleteEvent)
   * onSubmitComplete} event may not fire at all.
   * </p>
   *
   * @tip The initial implementation of FormPanel specified that the server
   *      respond with a content-type of 'text/plain'. This has been
   *      intentionally changed to specify 'text/html' because 'text/plain'
   *      cannot be made to work properly on all browsers.
   */
  public FormPanel() {
    this(Document.get().createFormElement(), true);
  }

  /**
   * Creates a FormPanel that targets a {@link NamedFrame}. The target frame is
   * not physically attached to the form, and must therefore still be added to a
   * panel elsewhere.
   *
   * <p>
   * When the FormPanel targets an external frame in this way, it will not fire
   * the FormSubmitComplete event.
   * </p>
   *
   * @param frameTarget the {@link NamedFrame} to be targetted
   */
  public FormPanel(NamedFrame frameTarget) {
    this(frameTarget.getName());
  }

  /**
   * Creates a new FormPanel. When created using this constructor, it will be
   * submitted either by replacing the current page, or to the named
   * &lt;iframe&gt;.
   *
   * <p>
   * When the FormPanel targets an external frame in this way, it will not fire
   * the FormSubmitComplete event.
   * </p>
   *
   * @param target the name of the &lt;iframe&gt; to receive the results of the
   *          submission, or <code>null</code> to specify that the current page
   *          be replaced
   */
  public FormPanel(String target) {
    super(Document.get().createFormElement());
    setTarget(target);
  }

  /**
   * This constructor may be used by subclasses to explicitly use an existing
   * element. This element must be a &lt;form&gt; element.
   *
   * <p>
   * The specified form element's target attribute will not be set, and the
   * {@link FormSubmitCompleteEvent} will not be fired.
   * </p>
   *
   * @param element the element to be used
   */
  protected FormPanel(Element element) {
    this(element, false);
  }

  /**
   * This constructor may be used by subclasses to explicitly use an existing
   * element. This element must be a &lt;form&gt; element.
   *
   * <p>
   * If the createIFrame parameter is set to <code>true</code>, then the wrapped
   * form's target attribute will be set to a hidden iframe. If not, the form's
   * target will be left alone, and the FormSubmitComplete event will not be
   * fired.
   * </p>
   *
   * @param element the element to be used
   * @param createIFrame <code>true</code> to create an &lt;iframe&gt; element
   *          that will be targeted by this form
   */
  protected FormPanel(Element element, boolean createIFrame) {
    super(element);
    FormElement.as(element);

    if (createIFrame) {
      assert ((getTarget() == null) || (getTarget().trim().length() == 0)) : "Cannot create target iframe if the form's target is already set.";

      // We use the module name as part of the unique ID to ensure that ids are
      // unique across modules.
      frameName = "FormPanel_" + GWT.getModuleName() + "_" + (++formId);
      setTarget(frameName);

      sinkEvents(Event.ONLOAD);
    }
  }

  /**
   * @deprecated Use {@link #addSubmitCompleteHandler} and
   *             {@link #addSubmitHandler} instead
   */
  @Deprecated
  public void addFormHandler(FormHandler handler) {
    ListenerWrapper.WrappedOldFormHandler.add(this, handler);
  }

  /**
   * Adds a {@link SubmitCompleteEvent} handler.
   *
   * @param handler the handler
   * @return the handler registration used to remove the handler
   */
  public HandlerRegistration addSubmitCompleteHandler(SubmitCompleteHandler handler) {
    return addHandler(handler, SubmitCompleteEvent.getType());
  }

  /**
   * Adds a {@link SubmitEvent} handler.
   *
   * @param handler the handler
   * @return the handler registration used to remove the handler
   */
  public HandlerRegistration addSubmitHandler(SubmitHandler handler) {
    return addHandler(handler, SubmitEvent.getType());
  }

  /**
   * Gets the 'action' associated with this form. This is the URL to which it
   * will be submitted.
   *
   * @return the form's action
   */
  public String getAction() {
    return getFormElement().getAction();
  }

  /**
   * Gets the encoding used for submitting this form. This should be either
   * {@link #ENCODING_MULTIPART} or {@link #ENCODING_URLENCODED}.
   *
   * @return the form's encoding
   */
  public String getEncoding() {
    return impl.getEncoding(getElement());
  }

  /**
   * Gets the HTTP method used for submitting this form. This should be either
   * {@link #METHOD_GET} or {@link #METHOD_POST}.
   *
   * @return the form's method
   */
  public String getMethod() {
    return getFormElement().getMethod();
  }

  /**
   * Gets the form's 'target'. This is the name of the {@link NamedFrame} that
   * will receive the results of submission, or <code>null</code> if none has
   * been specified.
   *
   * @return the form's target.
   */
  public String getTarget() {
    return getFormElement().getTarget();
  }

  /**
   * Fired when a form is submitted.
   *
   * @return true if the form is submitted, false if canceled
   */
  public boolean onFormSubmit() {
    return onFormSubmitImpl();
  }

  public void onFrameLoad() {
    onFrameLoadImpl();
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler} method on the
   *             object returned by and add*Handler method instead
   */
  @Deprecated
  public void removeFormHandler(FormHandler handler) {
    ListenerWrapper.WrappedOldFormHandler.remove(this, handler);
  }

  /**
   * Resets the form, clearing all fields.
   */
  public void reset() {
    impl.reset(getElement());
  }

  /**
   * Sets the 'action' associated with this form. This is the URL to which it
   * will be submitted.
   *
   * @param url the form's action
   */
  public void setAction(@IsSafeUri String url) {
    getFormElement().setAction(url);
  }

  /**
   * Sets the 'action' associated with this form. This is the URL to which it
   * will be submitted.
   *
   * @param url the form's action
   */
  public void setAction(SafeUri url) {
    getFormElement().setAction(url);
  }

  /**
   * Sets the encoding used for submitting this form. This should be either
   * {@link #ENCODING_MULTIPART} or {@link #ENCODING_URLENCODED}.
   *
   * @param encodingType the form's encoding
   */
  public void setEncoding(String encodingType) {
    impl.setEncoding(getElement(), encodingType);
  }

  /**
   * Sets the HTTP method used for submitting this form. This should be either
   * {@link #METHOD_GET} or {@link #METHOD_POST}.
   *
   * @param method the form's method
   */
  public void setMethod(String method) {
    getFormElement().setMethod(method);
  }

  /**
   * Submits the form.
   *
   * <p>
   * The FormPanel must <em>not</em> be detached (i.e. removed from its parent
   * or otherwise disconnected from a {@link RootPanel}) until the submission is
   * complete. Otherwise, notification of submission will fail.
   * </p>
   */
  public void submit() {
    // Fire the onSubmit event, because javascript's form.submit() does not
    // fire the built-in onsubmit event.
    if (!fireSubmitEvent()) {
      return;
    }

    impl.submit(getElement(), synthesizedFrame);
  }

  @Override
  protected void onAttach() {
    super.onAttach();

    if (frameName != null) {
      // Create and attach a hidden iframe to the body element.
      createFrame();
      Document.get().getBody().appendChild(synthesizedFrame);
    }
    // Hook up the underlying iframe's onLoad event when attached to the DOM.
    // Making this connection only when attached avoids memory-leak issues.
    // The FormPanel cannot use the built-in GWT event-handling mechanism
    // because there is no standard onLoad event on iframes that works across
    // browsers.
    impl.hookEvents(synthesizedFrame, getElement(), this);
  }

  @Override
  protected void onDetach() {
    super.onDetach();

    // Unhook the iframe's onLoad when detached.
    impl.unhookEvents(synthesizedFrame, getElement());

    if (synthesizedFrame != null) {
      // And remove it from the document.
      Document.get().getBody().removeChild(synthesizedFrame);
      synthesizedFrame = null;
    }
  }

  // For unit-tests.
  Element getSynthesizedIFrame() {
    return synthesizedFrame;
  }

  private void createFrame() {
    // Attach a hidden IFrame to the form. This is the target iframe to which
    // the form will be submitted. We have to create the iframe using innerHTML,
    // because setting an iframe's 'name' property dynamically doesn't work on
    // most browsers.
    Element dummy = Document.get().createDivElement();
    dummy.setInnerSafeHtml(IFrameTemplate.INSTANCE.get(frameName));

    synthesizedFrame = dummy.getFirstChildElement();
  }

  /**
   * Fire a {@link FormPanel.SubmitEvent}.
   *
   * @return true to continue, false if canceled
   */
  private boolean fireSubmitEvent() {
    FormPanel.SubmitEvent event = new FormPanel.SubmitEvent();
    fireEvent(event);
    return !event.isCanceled();
  }

  private FormElement getFormElement() {
    return getElement().cast();
  }

  /**
   * Returns true if the form is submitted, false if canceled.
   */
  private boolean onFormSubmitImpl() {
    return fireSubmitEvent();
  }

  private void onFrameLoadImpl() {
    // Fire onComplete events in a deferred command. This is necessary
    // because clients that detach the form panel when submission is
    // complete can cause some browsers (i.e. Mozilla) to go into an
    // 'infinite loading' state. See issue 916.
    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
      public void execute() {
        fireEvent(new SubmitCompleteEvent(impl.getContents(synthesizedFrame)));
      }
    });
  }

  private void setTarget(String target) {
    getFormElement().setTarget(target);
  }
}
