/*
 * 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.dom.client.DivElement;
import com.google.gwt.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.safehtml.shared.SafeHtml;

import java.util.NoSuchElementException;

/**
 * A panel that contains HTML, and which can attach child widgets to identified
 * elements within that HTML.
 */
public class HTMLPanel extends ComplexPanel {

  private static Element hiddenDiv;

  /**
   * A helper method for creating unique IDs for elements within dynamically-
   * generated HTML. This is important because no two elements in a document
   * should have the same id.
   * 
   * @return a new unique identifier
   */
  public static String createUniqueId() {
    return Document.get().createUniqueId();
  }

  /**
   * Creates an HTML panel with the specified HTML contents inside a DIV
   * element. Any element within this HTML that has a specified id can contain a
   * child widget.
   * 
   * @param html the panel's HTML
   */
  public HTMLPanel(String html) {
    /*
     * Normally would call this("div", html), but that method
     * has some slightly expensive IE defensiveness that we just
     * don't need for a div
     */
    setElement(Document.get().createDivElement());
    getElement().setInnerHTML(html);
  }
  
  /**
   * Initializes the panel's HTML from a given {@link SafeHtml} object.
   * 
   * Similar to {@link #HTMLPanel(String)}
   * 
   * @param safeHtml the html to set.
   */
  public HTMLPanel(SafeHtml safeHtml) {
    this(safeHtml.asString());
  }

  /**
   * Creates an HTML panel whose root element has the given tag, and with the
   * specified HTML contents. Any element within this HTML that has a specified
   * id can contain a child widget.
   * 
   * @param tag the tag of the root element
   * @param html the panel's HTML
   */
  public HTMLPanel(String tag, String html) {
    /*
     * IE has very arbitrary rules about what will and will not accept
     * innerHTML. <table> and <tbody> simply won't, the property is read only.
     * <p> will explode if you incorrectly try to put another <p> inside of it.
     * And who knows what else.
     * 
     * However, if you cram a complete, possibly incorrect structure inside a
     * div, IE will swallow it gladly. So that's what we do here in the name of
     * IE robustification.
     */
    StringBuilder b = new StringBuilder();
    b.append('<').append(tag).append('>').append(html);
    b.append("</").append(tag).append('>');
    
    // We could use the static hiddenDiv, but that thing is attached
    // to the document. The caller might not want that.
    
    DivElement scratchDiv = Document.get().createDivElement();
    scratchDiv.setInnerHTML(b.toString());
    setElement(scratchDiv.getFirstChildElement());
    getElement().removeFromParent();
  }
  
  /**
   * Adds a child widget to the panel, contained within the HTML element
   * specified by a given id.
   * 
   * @param widget the widget to be added
   * @param id the id of the element within which it will be contained
   */
  public void add(Widget widget, String id) {
    final Element elem = getElementById(id);

    if (elem == null) {
      throw new NoSuchElementException(id);
    }

    add(widget, elem);
  }

  /**
   * Adds a child widget to the panel, contained within an HTML
   * element.  It is up to the caller to ensure that the given element
   * is a child of this panel's root element.
   * 
   * @param widget the widget to be added
   * @param elem the element within which it will be contained
   */
  public void add(Widget widget, Element elem) {
    com.google.gwt.user.client.Element clientElem = elem.cast();
    super.add(widget, clientElem);
  }

  /**
   * Adds a child widget to the panel, replacing the HTML element.
   * 
   * @param widget the widget to be added
   * @param toReplace the element to be replaced by the widget
   */
  public final void addAndReplaceElement(Widget widget, Element toReplace) {
    com.google.gwt.user.client.Element clientElem = toReplace.cast();
    addAndReplaceElement(widget, clientElem);
  }
  
  /**
   * Adds a child widget to the panel, replacing the HTML element.
   * 
   * @param widget the widget to be added
   * @param toReplace the element to be replaced by the widget
   * @deprecated use {@link #addAndReplaceElement(Widget, Element)}
   */
  @Deprecated
  public void addAndReplaceElement(Widget widget,
      com.google.gwt.user.client.Element toReplace) {
    // Logic pulled from super.add(), replacing the element rather than adding.
    widget.removeFromParent();
    getChildren().add(widget);
    toReplace.getParentNode().replaceChild(widget.getElement(), toReplace);
    adopt(widget);
  }
  
  /**
   * Adds a child widget to the panel, replacing the HTML element specified by a
   * given id.
   * 
   * @param widget the widget to be added
   * @param id the id of the element to be replaced by the widget
   */
  public void addAndReplaceElement(Widget widget, String id) {
    final Element toReplace = getElementById(id);

    if (toReplace == null) {
      throw new NoSuchElementException(id);
    }
    
    addAndReplaceElement(widget, toReplace);
  }
  
  /**
   * Finds an {@link Element element} within this panel by its id.
   * 
   * This method uses
   * {@link com.google.gwt.dom.client.Document#getElementById(String)}, so the
   * id must still be unique within the document.
   * 
   * @param id the id of the element to be found
   * @return the element with the given id, or <code>null</code> if none is found
   */
  public com.google.gwt.user.client.Element getElementById(String id) {
    Element elem = isAttached() ? Document.get().getElementById(id) : attachToDomAndGetElement(id);
    return elem.cast();
  }

  /**
   * Performs a {@link DOM#getElementById(String)} after attaching the panel's
   * element into a hidden DIV in the document's body. Attachment is necessary
   * to be able to use the native getElementById. The panel's element will be
   * re-attached to its original parent (if any) after the method returns.
   * 
   * @param id the id whose associated element is to be retrieved
   * @return the associated element, or <code>null</code> if none is found
   */
  private Element attachToDomAndGetElement(String id) {
    // If the hidden DIV has not been created, create it.
    if (hiddenDiv == null) {
      hiddenDiv = Document.get().createDivElement();
      UIObject.setVisible(hiddenDiv, false);
      RootPanel.getBodyElement().appendChild(hiddenDiv);
    }

    // Hang on to the panel's original parent and sibling elements so that it
    // can be replaced.
    Element origParent = getElement().getParentElement();
    Element origSibling = getElement().getNextSiblingElement();

    // Attach the panel's element to the hidden div.
    hiddenDiv.appendChild(getElement());

    // Now that we're attached to the DOM, we can use getElementById.
    Element child = Document.get().getElementById(id);

    // Put the panel's element back where it was.
    if (origParent != null) {
      origParent.insertBefore(getElement(), origSibling);
    } else {
      hiddenDiv.removeChild(getElement());
    }

    return child;
  }
}
