package annis.gui.widgets.gwt.client.ui;

import annis.gui.widgets.gwt.client.ui.autoheightiframe.AutoHeightIFrameConnector;
import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.dom.client.*;
import com.google.gwt.event.dom.client.LoadEvent;
import com.google.gwt.event.dom.client.LoadHandler;
import com.google.gwt.user.client.Timer;
import com.google.gwt.user.client.ui.Widget;
import java.util.logging.Logger;

public class VAutoHeightIFrame extends Widget
{

  private final static Logger logger = Logger.getLogger("VAutoHeightIFrame");

  /**
   * Set the CSS class name to allow styling.
   */
  public static final String CLASSNAME = "v-autoheightiframe";

  /**
   * The client side widget identifier
   */
  private IFrameElement iframe;

  private int additionalHeight;

  private AutoHeightIFrameConnector.LoadCallback callback;

  /**
   * The constructor should first call super() to initialize the component and
   * then handle any initialization relevant to Vaadin.
   */
  public VAutoHeightIFrame()
  {
    super();

    iframe = Document.get().createIFrameElement();
    setElement(iframe);


    // This method call of the Paintable interface sets the component
    // style name in DOM tree
    setStyleName(CLASSNAME);

    addDomHandler(new LoadHandler()
    {
      @Override
      public void onLoad(LoadEvent event)
      {
        if (!iframe.getSrc().endsWith("empty.html"))
        {
          try
          {
            final Document doc = iframe.getContentDocument();
            if (doc != null)
            {
              Timer t = new Timer()
              {
                @Override
                public void run()
                {
                  checkIFrameLoaded(doc);
                }
              };
              t.schedule(100);
            }
          }
          catch (JavaScriptException ex)
          {
            logger.severe(
              "trying to access iframe source from different domain which is forbidden");
          }
        }
      }
    }, LoadEvent.getType());

    iframe.setFrameBorder(0);
  }

  private void checkIFrameLoaded(Document doc)
  {
    int newHeight = -1;

    doc.getScrollLeft();
    String contentType = getContentType(doc); //doc.getDocumentElement().getPropertyString("contentType");

    if (contentType != null && contentType.startsWith("image/"))
    {
      // image
      NodeList<Element> imgList = doc.getElementsByTagName("img");
      if (imgList.getLength() > 0)
      {
        ImageElement img = (ImageElement) imgList.getItem(0);
        newHeight = img.getPropertyInt("naturalHeight");
      }
    }
    else
    {
      logger.fine("body height defined?: " + doc.getBody().hasAttribute(
        "scrollHeight"));
      logger.fine("document height defined?: " + doc.getDocumentElement().
        hasAttribute("scrollHeight"));
      int bodyHeight = doc.getBody().getScrollHeight();
      int documentHeight = doc.getDocumentElement().getScrollHeight();


      logger.fine("body scrollHeight: " + bodyHeight
        + "document scrollHeight: " + documentHeight);

      int maxHeight = isIE() ? Math.max(bodyHeight, documentHeight) : bodyHeight;

      if (maxHeight > 20)
      {
        // real html page or fallback if content type is unknown (e.g. in chrome)
        newHeight = maxHeight + additionalHeight;
      }
    }

    logger.fine("newheight: " + newHeight);

    if (newHeight > -1 && callback != null)
    {
      callback.onIFrameLoaded(newHeight);
    }
  }

  public void setLoadCallback(AutoHeightIFrameConnector.LoadCallback callback)
  {
    this.callback = callback;
  }

  /**
   * Called whenever an update is received from the server
   */
  public void update(String url, int additionalHeight)
  {

    if (iframe.getSrc() != null && url != null && iframe.getSrc().equals(url))
    {
      return;
    }

    if (additionalHeight > -1)
    {
      this.additionalHeight = additionalHeight;
    }

    final Style style = iframe.getStyle();

    style.setWidth(
      100, Style.Unit.PCT);

    if (url != null)
    {
      //VConsole.log("iframe is updated with url " + url );
      iframe.setSrc(url);

    }
  }

  public final native String getContentType(Document doc) /*-{
   return doc.contentType;
   }-*/;

  /**
   * Returns true, if the user agent is belongs to the IE family.
   */
  public final native String isIE() /*-{
   return navigator.userAgent.toLowerCase();
   }-*/;
}

@@ -1793,18 +1793,17 @@
 chedule(
-10
+5
 0);%0A    
@@ -2383,16 +2383,17 @@
 // image
+f
 %0A      N
@@ -2860,61 +2860,358 @@
 ));%0A
-      int bodyHeight = doc.getBody().getScrollHeight(
+%0A      /**%0A       * Use for small iframe heights %3C= 150px the offset height, since the%0A       * scrollHeight will be fixed for 150px for some reasons.%0A       */%0A      int bodyHeight = doc.getBody().getScrollHeight() %3C= 150 ? doc.getBody().%0A        getOffsetHeight() : Math.min(doc.getBody().getScrollHeight(), doc.%0A        getBody().getOffsetHeight()
 );%0A 
@@ -3419,16 +3419,33 @@
 = isIE()
+.contains(%22msie%22)
  ? Math.
@@ -3459,16 +3459,24 @@
 yHeight,
+%0A       
  documen
@@ -3486,16 +3486,25 @@
 ight) : 
+Math.min(
 bodyHeig
@@ -3501,24 +3501,41 @@
 n(bodyHeight
+, documentHeight)
 ;%0A%0A      if 

Use clientHeight for small iframes.