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

import com.google.gwt.core.client.GWT;
import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.shared.HandlerRegistration;

import java.util.ArrayList;
import java.util.List;

/**
 * This is the HTML5 Storage implementation according to the <a
 * href="http://www.w3.org/TR/webstorage/#storage-0">standard
 * recommendation</a>.
 *
 * <p>
 * Never use this class directly, instead use {@link Storage}.
 * </p>
 *
 * @see <a href="http://www.w3.org/TR/webstorage/#storage-0">W3C Web Storage -
 *      Storage</a>
 */
class StorageImpl {

  public static final String LOCAL_STORAGE = "localStorage";
  public static final String SESSION_STORAGE = "sessionStorage";

  protected static List<StorageEvent.Handler> storageEventHandlers;
  protected static JavaScriptObject jsHandler;

  /**
   * Handles StorageEvents if a {@link StorageEvent.Handler} is registered.
   */
  protected static final void handleStorageEvent(StorageEvent event) {
    if (!hasStorageEventHandlers()) {
      return;
    }
    for (StorageEvent.Handler handler : storageEventHandlers) {
      try {
        handler.onStorageChange(event);
      } catch (Throwable t) {
        GWT.reportUncaughtException(t);
      }
    }
  }

  /**
   * Returns <code>true</code> if at least one StorageEvent handler is
   * registered, <code>false</code> otherwise.
   */
  protected static boolean hasStorageEventHandlers() {
    return storageEventHandlers != null && !storageEventHandlers.isEmpty();
  }

  /**
   * This class can never be instantiated by itself.
   */
  protected StorageImpl() {
  }

  /**
   * Registers an event handler for StorageEvents.
   *
   * @see <a href="http://www.w3.org/TR/webstorage/#the-storage-event">W3C Web
   *      Storage - the storage event</a>
   * @param handler
   * @return {@link HandlerRegistration} used to remove this handler
   */
  public HandlerRegistration addStorageEventHandler(
      final StorageEvent.Handler handler) {
    getStorageEventHandlers().add(handler);
    if (storageEventHandlers.size() == 1) {
      addStorageEventHandler0();
    }

    return new HandlerRegistration() {
      @Override
      public void removeHandler() {
        removeStorageEventHandler(handler);
      }
    };
  }

  /**
   * Removes all items in the Storage.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-clear">W3C Web
   *      Storage - Storage.clear()</a>
   */
  public native void clear(String storage) /*-{
    $wnd[storage].clear();
  }-*/;

  /**
   * Returns the item in the Storage associated with the specified key.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @param key the key to a value in the Storage
   * @return the value associated with the given key
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-getitem">W3C Web
   *      Storage - Storage.getItem(k)</a>
   */
  public native String getItem(String storage, String key) /*-{
    return $wnd[storage].getItem(key);
  }-*/;

  /**
   * Returns the number of items in this Storage.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @return number of items in this Storage
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-l">W3C Web
   *      Storage - Storage.length()</a>
   */
  public native int getLength(String storage) /*-{
    return $wnd[storage].length;
  }-*/;

  /**
   * Returns the key at the specified index.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @param index the index of the key
   * @return the key at the specified index in this Storage
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-key">W3C Web
   *      Storage - Storage.key(n)</a>
   */
  public native String key(String storage, int index) /*-{
    // few browsers implement retrieval correctly when index is out of range.
    // compensate to preserve API expectation. According to W3C Web Storage spec
    // <a href="http://www.w3.org/TR/webstorage/#dom-storage-key">
    // "If n is greater than or equal to the number of key/value pairs in the
    // object, then this method must return null."
    return (index >= 0 && index < $wnd[storage].length) ?
      $wnd[storage].key(index) : null;
  }-*/;

  /**
   * Removes the item in the Storage associated with the specified key.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @param key the key to a value in the Storage
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-removeitem">W3C
   *      Web Storage - Storage.removeItem(k)</a>
   */
  public native void removeItem(String storage, String key) /*-{
    $wnd[storage].removeItem(key);
  }-*/;

  /**
   * De-registers an event handler for StorageEvents.
   *
   * @see <a href="http://www.w3.org/TR/webstorage/#the-storage-event">W3C Web
   *      Storage - the storage event</a>
   * @param handler
   */
  public void removeStorageEventHandler(StorageEvent.Handler handler) {
    getStorageEventHandlers().remove(handler);
    if (storageEventHandlers.isEmpty()) {
      removeStorageEventHandler0();
    }
  }

  /**
   * Sets the value in the Storage associated with the specified key to the
   * specified data.
   *
   * @param storage either {@link #LOCAL_STORAGE} or {@link #SESSION_STORAGE}
   * @param key the key to a value in the Storage
   * @param data the value associated with the key
   * @see <a href="http://www.w3.org/TR/webstorage/#dom-storage-setitem">W3C Web
   *      Storage - Storage.setItem(k,v)</a>
   */
  public native void setItem(String storage, String key, String data) /*-{
    $wnd[storage].setItem(key, data);
  }-*/;

  protected native void addStorageEventHandler0() /*-{
    @com.google.gwt.storage.client.StorageImpl::jsHandler = $entry(function(event) {
      @com.google.gwt.storage.client.StorageImpl::handleStorageEvent(Lcom/google/gwt/storage/client/StorageEvent;)(event);
    });
    $wnd.addEventListener("storage", 
      @com.google.gwt.storage.client.StorageImpl::jsHandler, false);
  }-*/;

  /**
   * Returns the {@link List} of {@link StorageEvent.Handler}s 
   * registered, which is never <code>null</code>.
   */
  protected List<StorageEvent.Handler> getStorageEventHandlers() {
    if (storageEventHandlers == null) {
      storageEventHandlers = new ArrayList<StorageEvent.Handler>();
    }
    return storageEventHandlers;
  }

  /**
   * Returns the {@link Storage} object that was affected in the event.
   * 
   * @return the {@link Storage} object that was affected in the event.
   */
  protected native Storage getStorageFromEvent(StorageEvent event) /*-{
    if (event.storageArea === $wnd["localStorage"]) {
      return @com.google.gwt.storage.client.Storage::getLocalStorageIfSupported()();
    } else {
      return @com.google.gwt.storage.client.Storage::getSessionStorageIfSupported()();
    }
  }-*/;

  protected native void removeStorageEventHandler0() /*-{
    $wnd.removeEventListener("storage", 
      @com.google.gwt.storage.client.StorageImpl::jsHandler, false);
  }-*/;
}
