/*
 * Copyright 2009 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.dom.client.Element;
import com.google.gwt.editor.client.IsEditor;
import com.google.gwt.editor.ui.client.adapters.ValueBoxEditor;
import com.google.gwt.event.dom.client.ChangeEvent;
import com.google.gwt.event.dom.client.ChangeHandler;
import com.google.gwt.event.dom.client.HasChangeHandlers;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.i18n.client.AutoDirectionHandler;
import com.google.gwt.i18n.client.BidiPolicy;
import com.google.gwt.i18n.client.BidiUtils;
import com.google.gwt.i18n.shared.DirectionEstimator;
import com.google.gwt.i18n.shared.HasDirectionEstimator;
import com.google.gwt.text.shared.Parser;
import com.google.gwt.text.shared.Renderer;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.impl.TextBoxImpl;

import java.text.ParseException;

/**
 * Abstract base class for all text entry widgets.
 * 
 * <h3>Use in UiBinder Templates</h3>
 * 
 * @param <T> the value type
 */
public class ValueBoxBase<T> extends FocusWidget implements
    HasChangeHandlers, HasName, HasDirectionEstimator,
    HasValue<T>, HasText, AutoDirectionHandler.Target, IsEditor<ValueBoxEditor<T>> {

  /**
   * Alignment values for {@link ValueBoxBase#setAlignment}.
   */
  public enum TextAlignment {
    CENTER {
      @Override
      String getTextAlignString() {
        return "center";
      }
    },
    JUSTIFY {
      @Override
      String getTextAlignString() {
        return "justify";
      }
    },
    LEFT {
      @Override
      String getTextAlignString() {
        return "left";
      }
    },
    RIGHT {
      @Override
      String getTextAlignString() {
        return "right";
      }

    };
    abstract String getTextAlignString();
  }

  private static TextBoxImpl impl = GWT.create(TextBoxImpl.class);
  private final AutoDirectionHandler autoDirHandler;

  private final Parser<T> parser;
  private final Renderer<T> renderer;
  private ValueBoxEditor<T> editor;
  private Event currentEvent;

  private boolean valueChangeHandlerInitialized;

  /**
   * Creates a value box that wraps the given browser element handle. This is
   * only used by subclasses.
   * 
   * @param elem the browser element to wrap
   */
  protected ValueBoxBase(Element elem, Renderer<T> renderer, Parser<T> parser) {
    super(elem);
    autoDirHandler = AutoDirectionHandler.addTo(this,
        BidiPolicy.isBidiEnabled());
    this.renderer = renderer;
    this.parser = parser;
  }

  public HandlerRegistration addChangeHandler(ChangeHandler handler) {
    return addDomHandler(handler, ChangeEvent.getType());
  }

  public HandlerRegistration addValueChangeHandler(ValueChangeHandler<T> handler) {
    // Initialization code
    if (!valueChangeHandlerInitialized) {
      valueChangeHandlerInitialized = true;
      addChangeHandler(new ChangeHandler() {
        public void onChange(ChangeEvent event) {
          ValueChangeEvent.fire(ValueBoxBase.this, getValue());
        }
      });
    }
    return addHandler(handler, ValueChangeEvent.getType());
  }

  /**
   * Returns an Editor that is backed by the ValueBoxBase. The default
   * implementation returns {@link ValueBoxEditor#of(ValueBoxBase)}. Subclasses
   * may override this method to provide custom error-handling when using the
   * Editor framework.
   */
  public ValueBoxEditor<T> asEditor() {
    if (editor == null) {
      editor = ValueBoxEditor.of(this);
    }
    return editor;
  }

  /**
   * If a keyboard event is currently being handled on this text box, calling
   * this method will suppress it. This allows listeners to easily filter
   * keyboard input.
   */
  public void cancelKey() {
    if (currentEvent != null) {
      currentEvent.preventDefault();
    }
  }

  /**
   * Gets the current position of the cursor (this also serves as the beginning
   * of the text selection).
   * 
   * @return the cursor's position
   */
  public int getCursorPos() {
    return impl.getCursorPos(getElement());
  }

  public Direction getDirection() {
    return BidiUtils.getDirectionOnElement(getElement());
  }

  /**
   * Gets the direction estimation model of the auto-dir handler.
   */
  public DirectionEstimator getDirectionEstimator() {
    return autoDirHandler.getDirectionEstimator();
  }

  public String getName() {
    return getElement().getPropertyString("name");
  }

  /**
   * Gets the text currently selected within this text box.
   * 
   * @return the selected text, or an empty string if none is selected
   */
  public String getSelectedText() {
    int start = getCursorPos();
    if (start < 0) {
      return "";
    }
    int length = getSelectionLength();
    return getText().substring(start, start + length);
  }

  /**
   * Gets the length of the current text selection.
   * 
   * @return the text selection length
   */
  public int getSelectionLength() {
    return impl.getSelectionLength(getElement());
  }

  public String getText() {
    return getElement().getPropertyString("value");
  }

  /**
   * Return the parsed value, or null if the field is empty or parsing fails.
   */
  public T getValue() {
    try {
      return getValueOrThrow();
    } catch (ParseException e) {
      return null;
    }
  }

  /**
   * Return the parsed value, or null if the field is empty.
   * 
   * @throws ParseException if the value cannot be parsed
   */
  public T getValueOrThrow() throws ParseException {
    String text = getText();

    T parseResult = parser.parse(text);

    if ("".equals(text)) {
      return null;
    }

    return parseResult;
  }

  /**
   * Determines whether or not the widget is read-only.
   * 
   * @return <code>true</code> if the widget is currently read-only,
   *         <code>false</code> if the widget is currently editable
   */
  public boolean isReadOnly() {
    return getElement().getPropertyBoolean("readOnly");
  }

  @Override
  public void onBrowserEvent(Event event) {
    int type = DOM.eventGetType(event);
    if ((type & Event.KEYEVENTS) != 0) {
      // Fire the keyboard event. Hang on to the current event object so that
      // cancelKey() and setKey() can be implemented.
      currentEvent = event;
      // Call the superclass' onBrowserEvent as that includes the key event
      // handlers.
      super.onBrowserEvent(event);
      currentEvent = null;
    } else {
      // Handles Focus and Click events.
      super.onBrowserEvent(event);
    }
  }

  /**
   * @deprecated Use the {@link HandlerRegistration#removeHandler} method on the
   *             object returned by {@link #addChangeHandler} instead
   */
  @Deprecated
  public void removeChangeListener(ChangeListener listener) {
    ListenerWrapper.WrappedChangeListener.remove(this, listener);
  }

  /**
   * Selects all of the text in the box.
   * 
   * This will only work when the widget is attached to the document and not
   * hidden.
   */
  public void selectAll() {
    int length = getText().length();
    if (length > 0) {
      setSelectionRange(0, length);
    }
  }

  public void setAlignment(TextAlignment align) {
    getElement().getStyle().setProperty("textAlign", align.getTextAlignString());
  }

  /**
   * Sets the cursor position.
   * 
   * This will only work when the widget is attached to the document and not
   * hidden.
   * 
   * @param pos the new cursor position
   */
  public void setCursorPos(int pos) {
    setSelectionRange(pos, 0);
  }

  public void setDirection(Direction direction) {
    BidiUtils.setDirectionOnElement(getElement(), direction);
  }

  /**
   * Toggles on / off direction estimation.
   */
  public void setDirectionEstimator(boolean enabled) {
    autoDirHandler.setDirectionEstimator(enabled);
  }

  /**
   * Sets the direction estimation model of the auto-dir handler.
   */
  public void setDirectionEstimator(DirectionEstimator directionEstimator) {
    autoDirHandler.setDirectionEstimator(directionEstimator);
  }

  /**
   * If a keyboard event is currently being handled by the text box, this method
   * replaces the unicode character or key code associated with it. This allows
   * listeners to easily filter keyboard input.
   * 
   * @param key the new key value
   * @deprecated this method only works in IE and should not have been added to
   *             the API
   */
  @Deprecated
  public void setKey(char key) {
    if (currentEvent != null) {
      DOM.eventSetKeyCode(currentEvent, key);
    }
  }

  public void setName(String name) {
    getElement().setPropertyString("name", name);
  }

  /**
   * Turns read-only mode on or off.
   * 
   * @param readOnly if <code>true</code>, the widget becomes read-only; if
   *          <code>false</code> the widget becomes editable
   */
  public void setReadOnly(boolean readOnly) {
    getElement().setPropertyBoolean("readOnly", readOnly);
    String readOnlyStyle = "readonly";
    if (readOnly) {
      addStyleDependentName(readOnlyStyle);
    } else {
      removeStyleDependentName(readOnlyStyle);
    }
  }

  /**
   * Sets the range of text to be selected.
   * 
   * This will only work when the widget is attached to the document and not
   * hidden.
   * 
   * @param pos the position of the first character to be selected
   * @param length the number of characters to be selected
   */
  public void setSelectionRange(int pos, int length) {
    // Setting the selection range will not work for unattached elements.
    if (!isAttached()) {
      return;
    }

    if (length < 0) {
      throw new IndexOutOfBoundsException(
          "Length must be a positive integer. Length: " + length);
    }
    if (pos < 0 || length + pos > getText().length()) {
      throw new IndexOutOfBoundsException("From Index: " + pos + "  To Index: "
          + (pos + length) + "  Text Length: " + getText().length());
    }
    impl.setSelectionRange(getElement(), pos, length);
  }
  
  /**
   * Sets this object's text. Note that some browsers will manipulate the text
   * before adding it to the widget. For example, most browsers will strip all
   * <code>\r</code> from the text, except IE which will add a <code>\r</code>
   * before each <code>\n</code>. Use {@link #getText()} to get the text
   * directly from the widget.
   * 
   * @param text the object's new text
   */
  public void setText(String text) {
    getElement().setPropertyString("value", text != null ? text : "");
    autoDirHandler.refreshDirection();
  }

  public void setValue(T value) {
    setValue(value, false);
  }

  public void setValue(T value, boolean fireEvents) {
    T oldValue = fireEvents ? getValue() : null;
    setText(renderer.render(value));
    if (fireEvents) {
      T newValue = getValue();
      ValueChangeEvent.fireIfNotEqual(this, oldValue, newValue);
    }
  }

  protected TextBoxImpl getImpl() {
    return impl;
  }

  @Override
  protected void onLoad() {
    super.onLoad();
    autoDirHandler.refreshDirection();
  }
}
