// Copyright (C) 2010 The Android Open Source Project
//
// 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.gerrit.client.ui;

import com.google.gerrit.client.Gerrit;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.KeyCodes;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwtexpui.globalkey.client.NpTextBox;
import com.google.gwt.user.client.ui.SuggestBox;
import com.google.gwt.user.client.ui.Widget;
import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;


public class HintTextBox extends NpTextBox {
  private HandlerRegistration hintFocusHandler;
  private HandlerRegistration hintBlurHandler;
  private HandlerRegistration keyDownHandler;

  private String hintText;
  private String hintStyleName = Gerrit.RESOURCES.css().inputFieldTypeHint();

  private String prevText;

  private boolean hintOn;
  private boolean isFocused;


  public String getText() {
    if (hintOn) {
      return "";
    }
    return super.getText();
  }

  public void setText(String text) {
    focusHint();

    super.setText(text);
    prevText = text;

    if (! isFocused) {
      blurHint();
    }
  }

  public String getHintText() {
    return hintText;
  }

  public void setHintText(String text) {
    if (text == null) {
      if (hintText == null) { // was not set, still not set, no change.
        return;
      }

      // Clearing a previously set Hint
      hintFocusHandler.removeHandler();
      hintFocusHandler = null;
      hintBlurHandler.removeHandler();
      hintBlurHandler = null;
      keyDownHandler.removeHandler();
      keyDownHandler = null;
      hintText = null;
      focusHint();

      return;
    }

    // Setting Hints

    if (hintText == null) { // first time (was not already set)
      hintText = text;

      hintFocusHandler = addFocusHandler(new FocusHandler() {
          @Override
          public void onFocus(FocusEvent event) {
            focusHint();
            prevText = getText();
            isFocused = true;
          }
        });

      hintBlurHandler = addBlurHandler(new BlurHandler() {
          @Override
          public void onBlur(BlurEvent event) {
            blurHint();
            isFocused = false;
          }
        });

      /*
      * There seems to be a strange bug (at least on firefox 3.5.9 ubuntu) with
      * the textbox under the following circumstances:
      *  1) The field is not focused with BText in it.
      *  2) The field receives focus and a focus listener changes the text to FText
      *  3) The ESC key is pressed and the value of the field has not changed
      *     (ever) from FText
      *  4) BUG: The text value gets reset to BText!
      *
      *  A counter to this bug seems to be to force setFocus(false) on ESC.
      */

      /* Chrome does not create a KeyPressEvent on ESC, so use KeyDownEvents */
      keyDownHandler = addKeyDownHandler(new KeyDownHandler() {
          @Override
          public void onKeyDown(final KeyDownEvent event) {
            onKey(event.getNativeKeyCode());
          }
        });

    } else { // Changing an already set Hint

      focusHint();
      hintText = text;
    }

    if (! isFocused) {
      blurHint();
    }
  }

  private void onKey(int key) {
    if (key == KeyCodes.KEY_ESCAPE) {
      setText(prevText);

      Widget p = getParent();
      if (p instanceof SuggestBox) {
        // Since the text was changed, ensure that the SuggestBox is
        // aware of this change so that it will refresh properly on
        // the next keystroke.  Without this, if the first keystroke
        // recreates the same string as before ESC was pressed, the
        // SuggestBox will think that the string has not changed, and
        // it will not yet provide any Suggestions.
        ((SuggestBox)p).showSuggestionList();

        // The suggestion list lingers if we don't hide it.
        ((DefaultSuggestionDisplay) ((SuggestBox) p).getSuggestionDisplay())
            .hideSuggestions();
      }

      setFocus(false);
    }
  }

  public void setHintStyleName(String styleName) {
    if (hintStyleName != null && hintOn) {
      removeStyleName(hintStyleName);
    }

    hintStyleName = styleName;

    if (styleName != null && hintOn) {
      addStyleName(styleName);
    }
  }

  public String getHintStyleName() {
    return hintStyleName;
  }

  protected void blurHint() {
    if (! hintOn && getHintText() != null && "".equals(super.getText())) {
      hintOn = true;
      super.setText(getHintText());
      if (getHintStyleName() != null) {
        addStyleName(getHintStyleName());
      }
    }
  }

  protected void focusHint() {
    if (hintOn) {
      super.setText("");
      if (getHintStyleName() != null) {
        removeStyleName(getHintStyleName());
      }
      hintOn = false;
    }
  }

  public void setFocus(boolean focus) {
    super.setFocus(focus);

    if (focus != isFocused) {
      if (focus) {
        focusHint();
      } else {
        blurHint();
      }
    }

    isFocused = focus;
  }
}
