/*
 * Copyright 2007 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.i18n.client;

import com.google.gwt.core.client.JavaScriptObject;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.Set;

/**
 * Provides dynamic string lookup of key/value string pairs defined in a
 * module's host HTML page. Each unique instance of <code>Dictionary</code> is
 * bound to a named JavaScript object that resides in the global namespace of
 * the host page's window object. The bound JavaScript object is used directly
 * as an associative array.
 * 
 * <p>
 * For example, suppose you define the following JavaScript object in your host
 * page:
 * 
 * {@gwt.include com/google/gwt/examples/i18n/ThemeDictionaryExample.js}
 * 
 * You can then use a <code>Dictionary</code> to access the key/value pairs
 * above:
 * 
 * {@example com.google.gwt.examples.i18n.ThemeDictionaryExample#useThemeDictionary()}
 * </p>
 * 
 * <p>
 * Unlike the family of interfaces that extend
 * {@link com.google.gwt.i18n.client.Localizable} which support static
 * internationalization, the <code>Dictionary</code> class is fully dynamic.
 * As a result, a variety of error conditions (particularly those involving key
 * mismatches) cannot be caught until runtime. Similarly, the GWT compiler is
 * unable discard unused dictionary values since the structure cannot be
 * statically analyzed.
 * </p>
 * 
 * <h3>A Caveat Regarding Locale</h3>
 * The module's host page completely determines the mappings defined for each
 * dictionary without regard to the <code>locale</code> client property. Thus,
 * <code>Dictionary</code> is the most flexible of the internationalization
 * types and may provide the simplest form of integration with existing
 * localization systems which were not specifically designed to use GWT's
 * <code>locale</code> client property.
 * 
 * <p>
 * See {@link com.google.gwt.i18n.client.Localizable} for background on the
 * <code>locale</code> client property.
 * </p>
 * 
 * <h3>Required Module</h3>
 * Modules that use this interface should inherit
 * <code>com.google.gwt.i18n.I18N</code>.
 * 
 * {@gwt.include com/google/gwt/examples/i18n/InheritsExample.gwt.xml}
 */
public final class Dictionary {

  private static Map<String, Dictionary> cache =
    new HashMap<String, Dictionary>();
  private static final int MAX_KEYS_TO_SHOW = 20;

  /**
   * Returns the <code>Dictionary</code> object associated with the given
   * name.
   * 
   * @param name
   * @return specified dictionary
   * @throws MissingResourceException
   */
  public static Dictionary getDictionary(String name) {
    Dictionary target = cache.get(name);
    if (target == null) {
      target = new Dictionary(name);
      cache.put(name, target);
    }
    return target;
  }

  static void resourceErrorBadType(String name) {
    throw new MissingResourceException("'" + name
        + "' is not a JavaScript object and cannot be used as a Dictionary",
        null, name);
  }

  private JavaScriptObject accessedKeys;
  private JavaScriptObject dict;

  private String label;

  /**
   * Constructor for <code>Dictionary</code>.
   * 
   * @param name name of linked JavaScript Object
   */
  private Dictionary(String name) {
    if (name == null || "".equals(name)) {
      throw new IllegalArgumentException(
          "Cannot create a Dictionary with a null or empty name");
    }
    this.label = "Dictionary " + name;
    attach(name);
    if (dict == null) {
      throw new MissingResourceException(
          "Cannot find JavaScript object with the name '" + name + "'", name,
          null);
    }
    createAccessedKeysArray();
  }

  private native void createAccessedKeysArray() /*-{
    this.@com.google.gwt.i18n.client.Dictionary::accessedKeys = new Array();
  }-*/;

  /**
   * Get the value associated with the given Dictionary key.
   * 
   * We have to call Object.hasOwnProperty to verify that the value is
   * defined on this object, rather than a superclass, since normal Object
   * properties are also visible on this object.
   * 
   * @param key to lookup
   * @return the value
   * @throws MissingResourceException if the value is not found
   */
  public native String get(String key) /*-{
    // In Firefox, jsObject.hasOwnProperty(key) requires a primitive string
    key = String(key);
    var map = this.@com.google.gwt.i18n.client.Dictionary::dict;
    var value = map[key];
    var keys = this.@com.google.gwt.i18n.client.Dictionary::accessedKeys;
    keys.unshift(key);
    // only keep the last 30 elements. Shrink it when array exceeds 60
    if (keys.length > 60) {
      keys.splice(30);
    }
    if (value == null || !map.hasOwnProperty(key)) {
      this.@com.google.gwt.i18n.client.Dictionary::resourceError(Ljava/lang/String;)(key);
    }
    return String(value);
  }-*/;

  /**
   * The set of keys associated with this dictionary.
   * 
   * @return the Dictionary set
   */
  public Set<String> keySet() {
    HashSet<String> s = new HashSet<String>();
    addKeys(s);
    return s;
  }

  @Override
  public String toString() {
    return label;
  }

  /**
   * Collection of values associated with this dictionary.
   * 
   * @return the values
   */
  public Collection<String> values() {
    ArrayList<String> s = new ArrayList<String>();
    addValues(s);
    return s;
  }

  void resourceError(String key) {
    Collection<String> s = this.keySet();
    String error = "Cannot find '" + key + "' in " + this;
    if (s.size() < MAX_KEYS_TO_SHOW) {
      error += "\n keys found: " + s;
    }
    error += "\n accessed keys: " + accessedKeys;
    throw new MissingResourceException(error, this.toString(), key);
  }

  private native void addKeys(HashSet<String> s) /*-{
    var map = this.@com.google.gwt.i18n.client.Dictionary::dict
    for (var key in map) {
      if (map.hasOwnProperty(key)) {
        s.@java.util.HashSet::add(Ljava/lang/Object;)(key);
      }
    }
  }-*/;

  private native void addValues(ArrayList<String> s) /*-{
    var map = this.@com.google.gwt.i18n.client.Dictionary::dict
    for (var key in map) {
      if (map.hasOwnProperty(key)) {
        var value = this.@com.google.gwt.i18n.client.Dictionary::get(Ljava/lang/String;)(key);
        s.@java.util.ArrayList::add(Ljava/lang/Object;)(value);
      }
    }
  }-*/;

  private native void attach(String name)/*-{
    try {
      if (typeof($wnd[name]) != "object") {
        @com.google.gwt.i18n.client.Dictionary::resourceErrorBadType(Ljava/lang/String;)(name);
      }
      this.@com.google.gwt.i18n.client.Dictionary::dict = $wnd[name];
    } catch(e) {
      @com.google.gwt.i18n.client.Dictionary::resourceErrorBadType(Ljava/lang/String;)(name);
    }
  }-*/;
}
