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

import com.google.gwt.event.logical.shared.CloseEvent;
import com.google.gwt.event.logical.shared.CloseHandler;
import com.google.gwt.event.logical.shared.ResizeEvent;
import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;
import com.google.gwt.event.shared.HandlerManager;
import com.google.gwt.event.shared.GwtEvent.Type;
import com.google.gwt.user.client.Event.NativePreviewEvent;
import com.google.gwt.user.client.ui.Widget;

/**
 * Legacy listener support hierarchy root.
 * 
 * Note, this class and its subtypes all assume that the handlers are stored in
 * handler managers.
 * 
 * This class, and its children are used to gather the bulk of the legacy glue
 * code in one place, for easy deletion when Listener methods are deleted.
 * 
 * @param <T> listener type to be wrapped
 * @deprecated will be removed in GWT 2.0 with the handler listeners themselves
 */
@Deprecated
public abstract class BaseListenerWrapper<T> implements EventHandler {

  static class NativePreview extends BaseListenerWrapper<EventPreview>
      implements Event.NativePreviewHandler {
    @Deprecated
    public static void add(EventPreview listener) {
      Event.addNativePreviewHandler(new NativePreview(listener));
    }

    public static void remove(EventPreview listener) {
      baseRemove(Event.handlers, listener, NativePreviewEvent.getType());
    }

    private NativePreview(EventPreview listener) {
      super(listener);
    }

    public void onPreviewNativeEvent(NativePreviewEvent event) {
      // The legacy EventHandler should only fire if it is on the top of the
      // stack (ie. the last one added).
      if (event.isFirstHandler()) {
        if (!listener.onEventPreview(Event.as(event.getNativeEvent()))) {
          event.cancel();
        }
      }
    }
  }

  static class WrapHistory extends BaseListenerWrapper<HistoryListener>
      implements ValueChangeHandler<String> {
    @Deprecated
    public static void add(HistoryListener listener) {
      History.addValueChangeHandler(new WrapHistory(listener));
    }

    public static void remove(HandlerManager manager, HistoryListener listener) {
      baseRemove(manager, listener, ValueChangeEvent.getType());
    }

    private WrapHistory(HistoryListener listener) {
      super(listener);
    }

    public void onValueChange(ValueChangeEvent<String> event) {
      listener.onHistoryChanged(event.getValue());
    }
  }

  static class WrapWindowClose extends BaseListenerWrapper<WindowCloseListener>
      implements Window.ClosingHandler, CloseHandler<Window> {
    @Deprecated
    public static void add(WindowCloseListener listener) {
      WrapWindowClose handler = new WrapWindowClose(listener);
      Window.addWindowClosingHandler(handler);
      Window.addCloseHandler(handler);
    }

    public static void remove(HandlerManager manager,
        WindowCloseListener listener) {
      baseRemove(manager, listener, Window.ClosingEvent.getType(),
          CloseEvent.getType());
    }

    private WrapWindowClose(WindowCloseListener listener) {
      super(listener);
    }

    public void onClose(CloseEvent<Window> event) {
      listener.onWindowClosed();
    }

    public void onWindowClosing(Window.ClosingEvent event) {
      String message = listener.onWindowClosing();
      if (event.getMessage() == null) {
        event.setMessage(message);
      }
    }
  }

  static class WrapWindowResize extends
      BaseListenerWrapper<WindowResizeListener> implements ResizeHandler {
    @Deprecated
    public static void add(WindowResizeListener listener) {
      Window.addResizeHandler(new WrapWindowResize(listener));
    }

    public static void remove(HandlerManager manager,
        WindowResizeListener listener) {
      baseRemove(manager, listener, ResizeEvent.getType());
    }

    private WrapWindowResize(WindowResizeListener listener) {
      super(listener);
    }

    public void onResize(ResizeEvent event) {
      listener.onWindowResized(event.getWidth(), event.getHeight());
    }
  }

  static class WrapWindowScroll extends
      BaseListenerWrapper<WindowScrollListener> implements Window.ScrollHandler {
    @Deprecated
    public static void add(WindowScrollListener listener) {
      Window.addWindowScrollHandler(new WrapWindowScroll(listener));
    }

    public static void remove(HandlerManager manager,
        WindowScrollListener listener) {
      baseRemove(manager, listener, Window.ScrollEvent.getType());
    }

    private WrapWindowScroll(WindowScrollListener listener) {
      super(listener);
    }

    public void onWindowScroll(Window.ScrollEvent event) {
      listener.onWindowScrolled(event.getScrollLeft(), event.getScrollTop());
    }
  }

  /**
   * Helper method to remove all wrapped listeners from the given event types.
   * 
   * @param manager the manager to remove the listener from
   * @param listener the listener
   * @param types the event types to remove the listener from
   * @param <H>
   */
  // This is an internal helper method with the current formulation, we have
  // lost the info needed to make it safe by this point.
  @SuppressWarnings("unchecked")
  protected static <H extends EventHandler> void baseRemove(
      HandlerManager manager, Object listener, Type... types) {
    if (manager != null) {
      for (Type<H> key : types) {
        int handlerCount = manager.getHandlerCount(key);
        // We are removing things as we traverse, have to go backward
        for (int i = handlerCount - 1; i >= 0; i--) {
          H handler = manager.getHandler(key, i);
          if (handler instanceof BaseListenerWrapper
              && ((BaseListenerWrapper) handler).listener.equals(listener)) {
            manager.removeHandler(key, handler);
          }
        }
      }
    }
  }

  /**
   * Listener being wrapped.
   */
  final T listener;

  private Widget source;

  /**
   * Creates a new listener wrapper.
   * 
   * @param listener the listener to wrap
   */
  protected BaseListenerWrapper(T listener) {
    this.listener = listener;
  }

  /**
   * Sets the widget source to pass to the listeners. Source defaults to
   * event.getSource() if this method is not used.
   * 
   * @param source the source to provide as the listener's source
   */
  public void setSource(Widget source) {
    this.source = source;
  }

  /**
   * Gets the listener being wrapped.
   * 
   * @return the wrapped listener
   */
  protected T getListener() {
    return listener;
  }

  /**
   * Gets the widget source to pass to the listeners. Source defaults to
   * event.getSource() if not specified by {@link #setSource(Widget)}.
   * 
   * @param event the event
   * @return source the source to provide as the listener's source
   */
  protected Widget getSource(GwtEvent<?> event) {
    if (source == null) {
      return (Widget) event.getSource();
    } else {
      return source;
    }
  }
}
