/*
 * 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.impl;

import com.google.gwt.core.client.JavaScriptException;
import com.google.gwt.dom.client.Element;
import com.google.gwt.safehtml.shared.annotations.IsSafeHtml;
import com.google.gwt.safehtml.shared.annotations.SuppressIsSafeHtmlCastCheck;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.ui.RichTextArea;
import com.google.gwt.user.client.ui.RichTextArea.FontSize;
import com.google.gwt.user.client.ui.RichTextArea.Justification;

/**
 * Basic rich text platform implementation.
 *
 * <p>Deprecated, may be flattened into RichTextAreaImpl as it has no other
 * direct subclasses.</p>
 */
@Deprecated
public abstract class RichTextAreaImplStandard extends RichTextAreaImpl implements
    RichTextArea.Formatter {

  /**
   * The message displayed when the formatter is used before the RichTextArea
   * is initialized.
   */
  private static final String INACTIVE_MESSAGE = "RichTextArea formatters " +
      "cannot be used until the RichTextArea is attached and focused.";

  /**
   * Holds a cached copy of any user setHTML/setText/setEnabled actions until
   * the real text area is fully initialized.  Becomes <code>null</code> after
   * init.
   */
  private Element beforeInitPlaceholder = DOM.createDiv();

  /**
   * Set to true when the {@link RichTextArea} is attached to the page and
   * {@link #initElement()} is called.  If the {@link RichTextArea} is detached
   * before {@link #onElementInitialized()} is called, this will be set to
   * false.  See issue 1897 for details.
   */
  protected boolean initializing;

  /**
   * Indicates that the text area should be focused as soon as it is loaded.
   */
  private boolean isPendingFocus;

  /**
   * True when the element has been attached.
   */
  private boolean isReady;

  @Override
  public native Element createElement() /*-{
    return $doc.createElement('iframe');
  }-*/;

  public void createLink(String url) {
    execCommand("CreateLink", url);
  }

  public String getBackColor() {
    return queryCommandValue("BackColor");
  }

  public String getForeColor() {
    return queryCommandValue("ForeColor");
  }

  @Override
  public final String getHTML() {
    return beforeInitPlaceholder == null ? getHTMLImpl() : beforeInitPlaceholder.getInnerHTML();
  }

  @Override
  public final String getText() {
    return beforeInitPlaceholder == null ? getTextImpl() : beforeInitPlaceholder.getInnerText();
  }

  @Override
  public native void initElement()  /*-{
    // Most browsers don't like setting designMode until slightly _after_
    // the iframe becomes attached to the DOM. Any non-zero timeout will do
    // just fine.
    var _this = this;
    _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::onElementInitializing()();
    setTimeout($entry(function() {
      // We need to check to see if the content window still is there. It might not be if the RTA
      // first was attached to the DOM and then quickly was removed before the timeout fired.
      if (_this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow != null) {
        // Turn on design mode.
        _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.designMode = 'On';

        // Send notification that the iframe has reached design mode.
        _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplStandard::onElementInitialized()();
      }
    }), 1);
  }-*/;

  public void insertHorizontalRule() {
    execCommand("InsertHorizontalRule", null);
  }

  public void insertHTML(@IsSafeHtml String html) {
    execCommand("InsertHTML", html);
  }

  public void insertImage(String url) {
    execCommand("InsertImage", url);
  }

  public void insertOrderedList() {
    execCommand("InsertOrderedList", null);
  }

  public void insertUnorderedList() {
    execCommand("InsertUnorderedList", null);
  }

  public boolean isBold() {
    return queryCommandState("Bold");
  }

  @Override
  public boolean isEnabled() {
    return beforeInitPlaceholder == null ? isEnabledImpl()
        : !beforeInitPlaceholder.getPropertyBoolean("disabled");
  }

  public boolean isItalic() {
    return queryCommandState("Italic");
  }

  public boolean isStrikethrough() {
    return queryCommandState("Strikethrough");
  }

  public boolean isSubscript() {
    return queryCommandState("Subscript");
  }

  public boolean isSuperscript() {
    return queryCommandState("Superscript");
  }

  public boolean isUnderlined() {
    return queryCommandState("Underline");
  }

  public void leftIndent() {
    execCommand("Outdent", null);
  }

  public void redo() {
    execCommand("Redo", "false");
  }

  public void removeFormat() {
    execCommand("RemoveFormat", null);
  }

  public void removeLink() {
    execCommand("Unlink", "false");
  }

  public void rightIndent() {
    execCommand("Indent", null);
  }

  public void selectAll() {
    execCommand("SelectAll", null);
  }

  public void setBackColor(String color) {
    execCommand("BackColor", color);
  }

  @Override
  public void setEnabled(boolean enabled) {
    if (beforeInitPlaceholder == null) {
      setEnabledImpl(enabled);
    } else {
      beforeInitPlaceholder.setPropertyBoolean("disabled", !enabled);
    }
  }

  @Override
  public void setFocus(boolean focused) {
    if (initializing) {
      // Issue 3503: if we focus before the iframe is in design mode, the text
      // caret will not appear.
      isPendingFocus = focused;
    } else {
      setFocusImpl(focused);
    }
  }

  public void setFontName(String name) {
    execCommand("FontName", name);
  }

  public void setFontSize(FontSize fontSize) {
    execCommand("FontSize", Integer.toString(fontSize.getNumber()));
  }

  public void setForeColor(String color) {
    execCommand("ForeColor", color);
  }

  @Override
  public final void setHTML(@IsSafeHtml String html) {
    if (beforeInitPlaceholder == null) {
      setHTMLImpl(html);
    } else {
      beforeInitPlaceholder.setInnerHTML(html);
    }
  }

  public void setJustification(Justification justification) {
    if (justification == Justification.CENTER) {
      execCommand("JustifyCenter", null);
    } else if (justification == Justification.FULL) {
      execCommand("JustifyFull", null);
    } else if (justification == Justification.LEFT) {
      execCommand("JustifyLeft", null);
    } else if (justification == Justification.RIGHT) {
      execCommand("JustifyRight", null);
    }
  }

  @Override
  public final void setText(String text) {
    if (beforeInitPlaceholder == null) {
      setTextImpl(text);
    } else {
      beforeInitPlaceholder.setInnerText(text);
    }
  }

  public void toggleBold() {
    execCommand("Bold", "false");
  }

  public void toggleItalic() {
    execCommand("Italic", "false");
  }

  public void toggleStrikethrough() {
    execCommand("Strikethrough", "false");
  }

  public void toggleSubscript() {
    execCommand("Subscript", "false");
  }

  public void toggleSuperscript() {
    execCommand("Superscript", "false");
  }

  public void toggleUnderline() {
    execCommand("Underline", "False");
  }

  public void undo() {
    execCommand("Undo", "false");
  }

  @Override
  @SuppressIsSafeHtmlCastCheck
  public void uninitElement() {
    isReady = false;

    // Issue 1897: initElement uses a timeout, so its possible to call this
    // method after calling initElement, but before the event system is in
    // place.
    if (initializing) {
      initializing = false;
      return;
    }

    // Unhook all custom event handlers when the element is detached.
    unhookEvents();

    // Recreate the placeholder element and store the iframe's contents and the
    // enabled status in it. This is necessary because some browsers will wipe
    // the iframe's contents when it is removed from the DOM.
    @IsSafeHtml String html = getHTML(); // TODO: mXSS
    boolean enabled = isEnabled();
    beforeInitPlaceholder = DOM.createDiv();
    beforeInitPlaceholder.setInnerHTML(html);
    setEnabled(enabled);
  }

  protected native String getHTMLImpl() /*-{
    return this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.innerHTML;
  }-*/;

  protected native String getTextImpl() /*-{
    return this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.textContent;
  }-*/;

  @Override
  protected native void hookEvents() /*-{
    var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
    var wnd = elem.contentWindow;

    elem.__gwt_handler = $entry(function(evt) {
      @com.google.gwt.user.client.DOM::dispatchEvent(Lcom/google/gwt/user/client/Event;Lcom/google/gwt/dom/client/Element;)(evt, elem);
    });

    elem.__gwt_focusHandler = function(evt) {
      if (elem.__gwt_isFocused) {
        return;
      }

      elem.__gwt_isFocused = true;
      elem.__gwt_handler(evt);
    };

    elem.__gwt_blurHandler = function(evt) {
      if (!elem.__gwt_isFocused) {
        return;
      }

      elem.__gwt_isFocused = false;
      elem.__gwt_handler(evt);
    };

    wnd.addEventListener('keydown', elem.__gwt_handler, true);
    wnd.addEventListener('keyup', elem.__gwt_handler, true);
    wnd.addEventListener('keypress', elem.__gwt_handler, true);
    wnd.addEventListener('mousedown', elem.__gwt_handler, true);
    wnd.addEventListener('mouseup', elem.__gwt_handler, true);
    wnd.addEventListener('mousemove', elem.__gwt_handler, true);
    wnd.addEventListener('mouseover', elem.__gwt_handler, true);
    wnd.addEventListener('mouseout', elem.__gwt_handler, true);
    wnd.addEventListener('click', elem.__gwt_handler, true);

    wnd.addEventListener('focus', elem.__gwt_focusHandler, true);
    wnd.addEventListener('blur', elem.__gwt_blurHandler, true);
  }-*/;

  protected native boolean isEnabledImpl() /*-{
    var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
    return elem.contentWindow.document.designMode.toUpperCase() == 'ON';
  }-*/;

  @Override @SuppressIsSafeHtmlCastCheck
  protected void onElementInitialized() {
    // Issue 1897: This method is called after a timeout, during which time the
    // element might by detached.
    if (!initializing) {
      return;
    }
    initializing = false;
    isReady = true;

    // When the iframe is ready, ensure cached content is set.
    if (beforeInitPlaceholder != null) {
      setHTMLImpl(beforeInitPlaceholder.getInnerHTML());
      setEnabledImpl(isEnabled());
      beforeInitPlaceholder = null;
    }

    super.onElementInitialized();

    // Focus on the element now that it is initialized
    if (isPendingFocus) {
      isPendingFocus = false;
      setFocus(true);
    }
  }

  protected void onElementInitializing() {
    initializing = true;
    isPendingFocus = false;
  }

  protected native void setEnabledImpl(boolean enabled) /*-{
    var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
    elem.contentWindow.document.designMode = enabled ? 'On' : 'Off';
  }-*/;

  protected native void setFocusImpl(boolean focused) /*-{
   if (focused) {
      this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.focus();
    } else {
      this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.blur();
    }
  }-*/;

  protected native void setHTMLImpl(@IsSafeHtml String html) /*-{
    this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.innerHTML = html;
  }-*/;

  protected native void setTextImpl(String text) /*-{
    this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.body.textContent = text;
  }-*/;

  protected native void unhookEvents() /*-{
    var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem;
    var wnd = elem.contentWindow;

    wnd.removeEventListener('keydown', elem.__gwt_handler, true);
    wnd.removeEventListener('keyup', elem.__gwt_handler, true);
    wnd.removeEventListener('keypress', elem.__gwt_handler, true);
    wnd.removeEventListener('mousedown', elem.__gwt_handler, true);
    wnd.removeEventListener('mouseup', elem.__gwt_handler, true);
    wnd.removeEventListener('mousemove', elem.__gwt_handler, true);
    wnd.removeEventListener('mouseover', elem.__gwt_handler, true);
    wnd.removeEventListener('mouseout', elem.__gwt_handler, true);
    wnd.removeEventListener('click', elem.__gwt_handler, true);

    wnd.removeEventListener('focus', elem.__gwt_focusHandler, true);
    wnd.removeEventListener('blur', elem.__gwt_blurHandler, true);

    elem.__gwt_handler = null;
    elem.__gwt_focusHandler = null;
    elem.__gwt_blurHandler = null;
  }-*/;

  void execCommand(String cmd, String param) {
    assert isReady : INACTIVE_MESSAGE;
    if (isReady) {
      // When executing a command, focus the iframe first, since some commands
      // don't take properly when it's not focused.
      setFocus(true);
      try {
        execCommandAssumingFocus(cmd, param);
      } catch (JavaScriptException e) {
        // In mozilla, editing throws a JS exception if the iframe is
        // *hidden, but attached*.
      }
    }
  }

  native void execCommandAssumingFocus(String cmd, String param) /*-{
    this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.execCommand(cmd, false, param);
  }-*/;

  boolean queryCommandState(String cmd) {
    if (isReady) {
      // When executing a command, focus the iframe first, since some commands
      // don't take properly when it's not focused.
      setFocus(true);
      try {
        return queryCommandStateAssumingFocus(cmd);
      } catch (JavaScriptException e) { 
        return false;
      }
    }
    return false;
  }

  native boolean queryCommandStateAssumingFocus(String cmd) /*-{
    return !!this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.queryCommandState(cmd);
  }-*/;

  String queryCommandValue(String cmd) {
    if (isReady) {
      // When executing a command, focus the iframe first, since some commands
      // don't take properly when it's not focused.
      setFocus(true);
      try {
        return queryCommandValueAssumingFocus(cmd);
      } catch (JavaScriptException e) {
        return "";
      }
    }
    return "";
  }

  native String queryCommandValueAssumingFocus(String cmd) /*-{
    return this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.contentWindow.document.queryCommandValue(cmd);
  }-*/;
}
