/*
 * Copyright 2011 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.dom.client.Document;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.Style.Overflow;
import com.google.gwt.dom.client.Style.Position;
import com.google.gwt.dom.client.Style.Unit;
import com.google.gwt.dom.client.Style.Visibility;
import com.google.gwt.event.dom.client.HasScrollHandlers;
import com.google.gwt.event.dom.client.ScrollEvent;
import com.google.gwt.event.dom.client.ScrollHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.Event;

/**
 * Abstract parent class for scrollbars implemented using the native browser
 * scrollbars.
 */
public abstract class AbstractNativeScrollbar extends Widget implements HasScrollHandlers {

  private static int nativeHeight = -1;
  private static int nativeWidth = -1;
  private static boolean nativeRtl = false;

  /**
   * Get the height of a native horizontal scrollbar.
   * 
   * <p>
   * This method assumes that all native scrollbars on the page have the same
   * height.
   * 
   * @return the height in pixels
   */
  public static int getNativeScrollbarHeight() {
    maybeRecalculateNativeScrollbarSize();
    return nativeHeight;
  }

  /**
   * Get the width of a native vertical scrollbar.
   * 
   * <p>
   * This method assumes that all native vertical scrollbars on the page have
   * the same width.
   * 
   * @return the height in pixels
   */
  public static int getNativeScrollbarWidth() {
    maybeRecalculateNativeScrollbarSize();
    return nativeWidth;
  }

  /**
   * Check whether or not the native vertical scrollbar is aligned on the left
   * side of the scrollable element in RTL mode.
   * 
   * @return true if left aligned, false if not
   */
  public static boolean isScrollbarLeftAlignedInRtl() {
    maybeRecalculateNativeScrollbarSize();
    return nativeRtl;
  }

  /**
   * Recalculate the height and width of a native scrollbar.
   */
  private static void maybeRecalculateNativeScrollbarSize() {
    // Check if the size has already been calculated.
    if (nativeHeight > -1) {
      return;
    }

    // Create a scrollable element and attach it to the body.
    Element scrollable = Document.get().createDivElement();
    scrollable.getStyle().setPosition(Position.ABSOLUTE);
    scrollable.getStyle().setTop(0.0, Unit.PX);
    scrollable.getStyle().setLeft(0.0, Unit.PX);
    scrollable.getStyle().setHeight(100.0, Unit.PX);
    scrollable.getStyle().setWidth(100.0, Unit.PX);
    scrollable.getStyle().setOverflow(Overflow.SCROLL);
    scrollable.getStyle().setVisibility(Visibility.HIDDEN);
    scrollable.getStyle().setProperty("direction", "rtl");
    Document.get().getBody().appendChild(scrollable);

    // Add some content.
    Element content = Document.get().createDivElement();
    content.setInnerText("content");
    scrollable.appendChild(content);

    // Measure the height and width.
    nativeHeight = scrollable.getOffsetHeight() - scrollable.getClientHeight();
    nativeWidth = scrollable.getOffsetWidth() - scrollable.getClientWidth();
    nativeRtl = (content.getAbsoluteLeft() > scrollable.getAbsoluteLeft());

    // Detach the scrollable element.
    scrollable.removeFromParent();
  }

  public HandlerRegistration addScrollHandler(ScrollHandler handler) {
    // Sink the event on the scrollable element, not the root element.
    Event.sinkEvents(getScrollableElement(), Event.ONSCROLL);
    return addHandler(handler, ScrollEvent.getType());
  }

  /**
   * Get the scrollable element.
   * 
   * @return the scrollable element
   */
  protected abstract Element getScrollableElement();

  @Override
  protected void onAttach() {
    super.onAttach();

    /*
     * Attach the event listener in onAttach instead of onLoad so users cannot
     * accidentally override it.
     */
    Event.setEventListener(getScrollableElement(), this);
  }

  @Override
  protected void onDetach() {
    /*
     * Detach the event listener in onDetach instead of onUnload so users cannot
     * accidentally override it.
     */
    Event.setEventListener(getScrollableElement(), null);

    super.onDetach();
  }
}
