/*
 * 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.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.HasDirection.Direction;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.i18n.shared.HasDirectionEstimator;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Element;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.ui.impl.HyperlinkImpl;

/**
 * A widget that serves as an "internal" hyperlink. That is, it is a link to
 * another state of the running application. When clicked, it will create a new
 * history frame using {@link com.google.gwt.user.client.History#newItem}, but
 * without reloading the page.
 * 
 * <p>
 * If you want an HTML hyperlink (&lt;a&gt; tag) without interacting with the
 * history system, use {@link Anchor} instead.
 * </p>
 * 
 * <p>
 * Being a true hyperlink, it is also possible for the user to "right-click,
 * open link in new window", which will cause the application to be loaded in a
 * new window at the state specified by the hyperlink.
 * </p>
 * 
 * <p>
 * <h3>Built-in Bidi Text Support</h3>
 * This widget is capable of automatically adjusting its direction according to
 * its content. This feature is controlled by {@link #setDirectionEstimator} or
 * passing a DirectionEstimator parameter to the constructor, and is off by
 * default.
 * </p>
 *
 * <p>
 * <img class='gallery' src='doc-files/Hyperlink.png'/>
 * </p>
 * 
 * <h3>CSS Style Rules</h3>
 * <ul class='css'>
 * <li>.gwt-Hyperlink { }</li>
 * </ul>
 * 
 * <p>
 * <h3>Example</h3> {@example com.google.gwt.examples.HistoryExample}
 * </p>
 * 
 * @see Anchor
 */
@SuppressWarnings("deprecation")
public class Hyperlink extends Widget implements HasHTML, SourcesClickEvents,
    HasClickHandlers, HasDirectionEstimator, HasDirectionalSafeHtml {

  public static final DirectionEstimator DEFAULT_DIRECTION_ESTIMATOR =
      DirectionalTextHelper.DEFAULT_DIRECTION_ESTIMATOR;

  private static HyperlinkImpl impl = GWT.create(HyperlinkImpl.class);

  protected final DirectionalTextHelper directionalTextHelper;
  private final Element anchorElem = DOM.createAnchor();
  private String targetHistoryToken;

  /**
   * Creates an empty hyperlink.
   */
  public Hyperlink() {
    this(DOM.createDiv());
  }

  /**
   * Creates a hyperlink with its html and target history token specified.
   *
   * @param html the hyperlink's safe html
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  public Hyperlink(SafeHtml html, String targetHistoryToken) {
    this(html.asString(), true, targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its html and target history token specified.
   *
   * @param html the hyperlink's safe html
   * @param dir the html's direction
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  public Hyperlink(SafeHtml html, Direction dir, String targetHistoryToken) {
    this(html.asString(), true, dir, targetHistoryToken);
  }
  
  /**
   * Creates a hyperlink with its html and target history token specified.
   *
   * @param html the hyperlink's safe html
   * @param directionEstimator A DirectionEstimator object used for automatic
   *          direction adjustment. For convenience,
   *          {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  public Hyperlink(SafeHtml html, DirectionEstimator directionEstimator,
      String targetHistoryToken) {
    this(html.asString(), true, directionEstimator, targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its text and target history token specified.
   *
   * @param text the hyperlink's text
   * @param targetHistoryToken the history token to which it will link, which
   *          may not be null (use {@link Anchor} instead if you don't need
   *          history processing)
   */
  public Hyperlink(String text, String targetHistoryToken) {
    this(text, false, targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its text and target history token specified.
   * 
   * @param text the hyperlink's text
   * @param dir the text's direction
   * @param targetHistoryToken the history token to which it will link, which
   *          may not be null (use {@link Anchor} instead if you don't need
   *          history processing)
   */
  public Hyperlink(String text, Direction dir, String targetHistoryToken) {
    this(text, false, dir, targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its text and target history token specified.
   * 
   * @param text the hyperlink's text
   * @param directionEstimator A DirectionEstimator object used for automatic
   *          direction adjustment. For convenience,
   *          {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
   * @param targetHistoryToken the history token to which it will link, which
   *          may not be null (use {@link Anchor} instead if you don't need
   *          history processing)
   */
  public Hyperlink(String text, DirectionEstimator directionEstimator,
      String targetHistoryToken) {
    this(text, false, directionEstimator, targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its text and target history token specified.
   *
   * @param text the hyperlink's text
   * @param asHTML <code>true</code> to treat the specified text as html
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  public Hyperlink(String text, boolean asHTML, String targetHistoryToken) {
    this();
    directionalTextHelper.setTextOrHtml(text, asHTML);
    setTargetHistoryToken(targetHistoryToken);
  }
  
  protected Hyperlink(Element elem) {
    if (elem == null) {
      setElement(anchorElem);
    } else {
      setElement(elem);
      DOM.appendChild(getElement(), anchorElem);
    }

    sinkEvents(Event.ONCLICK);
    setStyleName("gwt-Hyperlink");
    directionalTextHelper = new DirectionalTextHelper(anchorElem,
        /* is inline */ true);
  }

  /**
   * Creates a hyperlink with its text target history token specified.
   *
   * @param text the hyperlink's text
   * @param asHTML <code>true</code> to treat the specified text as html
   * @param dir the text's direction
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  private Hyperlink(String text, boolean asHTML, Direction dir,
      String targetHistoryToken) {
    this();
    directionalTextHelper.setTextOrHtml(text, dir, asHTML);
    setTargetHistoryToken(targetHistoryToken);
  }

  /**
   * Creates a hyperlink with its text and target history token specified.
   *
   * @param text the hyperlink's text
   * @param asHTML <code>true</code> to treat the specified text as html
   * @param directionEstimator A DirectionEstimator object used for automatic
   *          direction adjustment. For convenience,
   *          {@link #DEFAULT_DIRECTION_ESTIMATOR} can be used.
   * @param targetHistoryToken the history token to which it will link
   * @see #setTargetHistoryToken
   */
  private Hyperlink(String text, boolean asHTML,
      DirectionEstimator directionEstimator, String targetHistoryToken) {
    this();
    directionalTextHelper.setDirectionEstimator(directionEstimator);
    directionalTextHelper.setTextOrHtml(text, asHTML);
    setTargetHistoryToken(targetHistoryToken);
  }

  /**
   * @deprecated Use {@link Anchor#addClickHandler} instead and call
   *     History.newItem from the handler if you need to process the
   *     click before the history token is set.
   */
  @Deprecated
  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return addHandler(handler, ClickEvent.getType());
  }

  /**
   * @deprecated Use {@link Anchor#addClickHandler} instead and call
   *     History.newItem from the handler if you need to process the
   *     click before the history token is set.
   */
  @Deprecated
  public void addClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.add(this, listener);
  }

  public DirectionEstimator getDirectionEstimator() {
    return directionalTextHelper.getDirectionEstimator();
  }

  public String getHTML() {
    return directionalTextHelper.getTextOrHtml(true);
  }

  /**
   * Gets the history token referenced by this hyperlink.
   * 
   * @return the target history token
   * @see #setTargetHistoryToken
   */
  public String getTargetHistoryToken() {
    return targetHistoryToken;
  }

  public String getText() {
    return directionalTextHelper.getTextOrHtml(false);
  }

  public Direction getTextDirection() {
    return directionalTextHelper.getTextDirection();
  }

  @Override
  public void onBrowserEvent(Event event) {
    super.onBrowserEvent(event);
    if (DOM.eventGetType(event) == Event.ONCLICK && impl.handleAsClick(event)) {
      History.newItem(getTargetHistoryToken());
      DOM.eventPreventDefault(event);
    }
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler}
   * method on the object returned by an add*Handler method instead
   */
  @Deprecated
  public void removeClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.remove(this, listener);
  }

  /**
   * {@inheritDoc}
   * <p>
   * See note at {@link #setDirectionEstimator(DirectionEstimator)}.
   */
  public void setDirectionEstimator(boolean enabled) {
    directionalTextHelper.setDirectionEstimator(enabled);
  }

  /**
   * {@inheritDoc}
   * <p>
   * Note: DirectionEstimator should be set before the widget has any content;
   * it's highly recommended to set it using a constructor. Reason: if the
   * widget already has non-empty content, this will update its direction
   * according to the new estimator's result. This may cause flicker, and thus
   * should be avoided.
   */
  public void setDirectionEstimator(DirectionEstimator directionEstimator) {
    directionalTextHelper.setDirectionEstimator(directionEstimator);
  }

  public void setHTML(SafeHtml html) {
    setHTML(html.asString());
  }

  public void setHTML(String html) {
    directionalTextHelper.setTextOrHtml(html, true);
  }

  public void setHTML(SafeHtml html, Direction dir) {
    directionalTextHelper.setTextOrHtml(html.asString(), dir, true);
  }

  /**
   * Sets the history token referenced by this hyperlink. This is the history
   * token that will be passed to {@link History#newItem} when this link is
   * clicked.
   *
   * @param targetHistoryToken the new history token, which may not be null (use
   *          {@link Anchor} instead if you don't need history processing)
   */
  public void setTargetHistoryToken(String targetHistoryToken) {
    assert targetHistoryToken != null
      : "targetHistoryToken must not be null, consider using Anchor instead";
    this.targetHistoryToken = targetHistoryToken;
    DOM.setElementProperty(anchorElem, "href", "#" + targetHistoryToken);
  }

  public void setText(String text) {
    directionalTextHelper.setTextOrHtml(text, false);
  }

  public void setText(String text, Direction dir) {
    directionalTextHelper.setTextOrHtml(text, dir, false);
  }

  /**
   * <b>Affected Elements:</b>
   * <ul>
   * <li>-wrapper = the div around the link.</li>
   * </ul>
   * 
   * @see UIObject#onEnsureDebugId(String)
   */
  @Override
  protected void onEnsureDebugId(String baseID) {
    ensureDebugId(anchorElem, "", baseID);
    ensureDebugId(getElement(), baseID, "wrapper");
  }
}
