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

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

import java.util.AbstractMap;
import java.util.AbstractSet;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;

/**
 * Map used when creating <code>Constants</code> maps. This class is to be
 * used only by the GWT code. The map is immediately wrapped in
 * Collections.unmodifiableMap(..) preventing any changes after construction.
 */
public class ConstantMap extends AbstractMap<String, String> {

  private static final class EntryImpl implements Entry<String, String> {
    private final String key;
    private final String value;

    private EntryImpl(String key, String value) {
      assert (key != null);
      assert (value != null);
      this.key = key;
      this.value = value;
    }

    @Override
    public boolean equals(Object o) {
      if (o instanceof Map.Entry<?, ?>) {
        Map.Entry<?, ?> other = (Map.Entry<?, ?>) o;
        // Key and value known to be non-null.
        if (key.equals(other.getKey()) && value.equals(other.getValue())) {
          return true;
        }
      }
      return false;
    }

    public String getKey() {
      return key;
    }

    public String getValue() {
      return value;
    }

    /**
     * Calculate the hash code using Sun's specified algorithm.
     */
    @Override
    public int hashCode() {
      int keyHash = 0;
      int valueHash = 0;
      if (getKey() != null) {
        keyHash = getKey().hashCode();
      }
      if (getValue() != null) {
        valueHash = getValue().hashCode();
      }
      return keyHash ^ valueHash;
    }

    public String setValue(String value) {
      throw new UnsupportedOperationException();
    }

    @Override
    public String toString() {
      return key + "=" + value;
    }
  }

  /**
   * The original set of keys.
   */
  private final String[] keys;

  /*
   * Stores a fast lookup in a JSO using ':' to prevent conflict with built-in
   * JavaScript properties.
   */
  @SuppressWarnings("unused")
  private JavaScriptObject map;

  public ConstantMap(String keys[], String values[]) {
    this.keys = keys;

    init();

    for (int i = 0; i < keys.length; ++i) {
      assert keys[i] != null;
      assert values[i] != null;
      putImpl(keys[i], values[i]);
    }
  }

  @Override
  public boolean containsKey(Object key) {
    return get(key) != null;
  }

  @Override
  public Set<Map.Entry<String, String>> entrySet() {
    return new AbstractSet<Entry<String, String>>() {
      @Override
      public boolean contains(Object o) {
        if (!(o instanceof Entry<?, ?>)) {
          return false;
        }
        Entry<?, ?> other = (Entry<?, ?>) o;
        String value = get(other.getKey());
        if (value != null && value.equals(other.getValue())) {
          return true;
        }
        return false;
      }

      @Override
      public Iterator<Map.Entry<String, String>> iterator() {
        return new Iterator<Entry<String, String>>() {
          private int next = 0;

          public boolean hasNext() {
            return next < ConstantMap.this.size();
          }

          public Entry<String, String> next() {
            if (!hasNext()) {
              throw new NoSuchElementException();
            }
            String key = keys[next++];
            return new EntryImpl(key, get(key));
          }

          public void remove() {
            throw new UnsupportedOperationException();
          }
        };
      }

      @Override
      public int size() {
        return ConstantMap.this.size();
      }
    };
  }

  @Override
  public String get(Object key) {
    return (key instanceof String) ? get((String) key) : null;
  }

  public native String get(String key) /*-{
    // Prepend ':' to avoid conflicts with built-in Object properties.
    return this.@com.google.gwt.i18n.client.impl.ConstantMap::map[':' + key];
  }-*/;

  @Override
  public Set<String> keySet() {
    return new AbstractSet<String>() {
      @Override
      public boolean contains(Object o) {
        return containsKey(o);
      }

      @Override
      public Iterator<String> iterator() {
        return Arrays.asList(keys).iterator();
      }

      @Override
      public int size() {
        return ConstantMap.this.size();
      }
    };
  }

  @Override
  public int size() {
    return keys.length;
  }

  /**
   * Overridable for testing purposes, see ConstantMapTest.
   */
  protected void init() {
    map = JavaScriptObject.createObject();
  }

  protected native void putImpl(String key, String value) /*-{
    // Prepend ':' to avoid conflicts with built-in Object properties.
    this.@com.google.gwt.i18n.client.impl.ConstantMap::map[':' + key] = value;
  }-*/;
}
