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

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

/**
 * Parses the string representation of a JSON object into a set of
 * JSONValue-derived objects.
 * 
 * @see com.google.gwt.json.client.JSONValue
 */
public class JSONParser {

  static final JavaScriptObject typeMap = initTypeMap();

  /**
   * Evaluates a trusted JSON string and returns its JSONValue representation.
   * CAUTION! This method calls the JavaScript <code>eval()</code> function,
   * which can execute arbitrary script. DO NOT pass an untrusted string into
   * this method.
   * 
   * <p>
   * This method has been deprecated. Please call either
   * {@link #parseStrict(String)} (for inputs that strictly follow the JSON
   * specification) or {@link #parseLenient(String)}. The implementation of this
   * method calls parseLenient.
   * 
   * @param jsonString a JSON object to parse
   * @return a JSONValue that has been built by parsing the JSON string
   * @throws NullPointerException if <code>jsonString</code> is
   *           <code>null</code>
   * @throws IllegalArgumentException if <code>jsonString</code> is empty
   * 
   * @deprecated use {@link #parseStrict(String)}
   */
  @Deprecated
  public static JSONValue parse(String jsonString) {
    return parseLenient(jsonString);
  }

  /**
   * Evaluates a trusted JSON string and returns its JSONValue representation.
   * CAUTION! This method calls the JavaScript {@code eval()} function, which
   * can execute arbitrary script. DO NOT pass an untrusted string into this
   * method.
   * 
   * @param jsonString a JSON object to parse
   * @return a JSONValue that has been built by parsing the JSON string
   * @throws NullPointerException if <code>jsonString</code> is
   *           <code>null</code>
   * @throws IllegalArgumentException if <code>jsonString</code> is empty
   * @deprecated use {@link #parseStrict(String)}
   */
  @Deprecated
  public static JSONValue parseLenient(String jsonString) {
    return parse(jsonString, false);
  }

  /**
   * Evaluates a JSON string and returns its JSONValue representation. The
   * browser's {@code JSON.parse function} is used.
   *
   * @param jsonString a JSON object to parse
   * @return a JSONValue that has been built by parsing the JSON string
   * @throws NullPointerException if <code>jsonString</code> is <code>null</code>
   * @throws IllegalArgumentException if <code>jsonString</code> is empty
   */
  public static JSONValue parseStrict(String jsonString) {
    return parse(jsonString, true);
  }
  
  static void throwJSONException(String message) {
    throw new JSONException(message);
  }

  static void throwUnknownTypeException(String typeString) {
    throw new JSONException("Unexpected typeof result '" + typeString
        + "'; please report this bug to the GWT team");
  }

  /**
   * Called from {@link #initTypeMap()}.
   */
  private static JSONValue createBoolean(boolean v) {
    return JSONBoolean.getInstance(v);
  }

  /**
   * Called from {@link #initTypeMap()}.
   */
  private static JSONValue createNumber(double v) {
    return new JSONNumber(v);
  }

  /**
   * Called from {@link #initTypeMap()}. If we get here, <code>o</code> is
   * either <code>null</code> (not <code>undefined</code>) or a JavaScript
   * object.
   */
  private static native JSONValue createObject(Object o) /*-{
    if (!o) {
      return @com.google.gwt.json.client.JSONNull::getInstance()();
    }
    var v = o.valueOf ? o.valueOf() : o;
    if (v !== o) {
      // It was a primitive wrapper, unwrap it and try again.
      var func = @com.google.gwt.json.client.JSONParser::typeMap[typeof v];
      return func ? func(v) : @com.google.gwt.json.client.JSONParser::throwUnknownTypeException(Ljava/lang/String;)(typeof v);
    } else if (o instanceof Array || o instanceof $wnd.Array) {
      // Looks like an Array; wrap as JSONArray.
      // NOTE: this test can fail for objects coming from a different window,
      // but we know of no reliable tests to determine if something is an Array
      // in all cases.
      return @com.google.gwt.json.client.JSONArray::new(Lcom/google/gwt/core/client/JavaScriptObject;)(o);
    } else {
      // This is a basic JavaScript object; wrap as JSONObject.
      // Subobjects will be created on demand.
      return @com.google.gwt.json.client.JSONObject::new(Lcom/google/gwt/core/client/JavaScriptObject;)(o);
    }
  }-*/;

  /**
   * Called from {@link #initTypeMap()}.
   */
  private static JSONValue createString(String v) {
    return new JSONString(v);
  }

  /**
   * Called from {@link #initTypeMap()}. This method returns a <code>null</code>
   * pointer, representing JavaScript <code>undefined</code>.
   */
  private static JSONValue createUndefined() {
    return null;
  }

  /**
   * This method converts <code>jsonString</code> into a JSONValue.
   * In strict mode (strict == true), one of two code paths is taken:
   * 1) Call JSON.parse, or
   * 2) Validate the input and call eval()
   * 
   * In lenient mode (strict == false), eval() is called without validation.
   * 
   * @param strict if true, parse in strict mode. 
   */
  private static native JSONValue evaluate(String json, boolean strict) /*-{
    // Note: we cannot simply call JsonUtils.unsafeEval because it is unable
    // to return a result for inputs whose outermost type is 'string' in
    // dev mode.
    var v;
    if (strict) {
      try {
        v = JSON.parse(json);
      } catch (e) {
        return @com.google.gwt.json.client.JSONParser::throwJSONException(Ljava/lang/String;)("Error parsing JSON: " + e);
      }
    } else {
      json = @com.google.gwt.core.client.JsonUtils::escapeJsonForEval(Ljava/lang/String;)(json);
      try {
        v = eval('(' + json + ')');
      } catch (e) { 
        return @com.google.gwt.json.client.JSONParser::throwJSONException(Ljava/lang/String;)("Error parsing JSON: " + e);
      }
    }
    var func = @com.google.gwt.json.client.JSONParser::typeMap[typeof v];
    return func ? func(v) : @com.google.gwt.json.client.JSONParser::throwUnknownTypeException(Ljava/lang/String;)(typeof v);
  }-*/;

  private static native JavaScriptObject initTypeMap() /*-{
    return {
      "boolean": @com.google.gwt.json.client.JSONParser::createBoolean(Z),
      "number": @com.google.gwt.json.client.JSONParser::createNumber(D),
      "string": @com.google.gwt.json.client.JSONParser::createString(Ljava/lang/String;),
      "object": @com.google.gwt.json.client.JSONParser::createObject(Ljava/lang/Object;),
      "function": @com.google.gwt.json.client.JSONParser::createObject(Ljava/lang/Object;),
      "undefined": @com.google.gwt.json.client.JSONParser::createUndefined(),
    }
  }-*/;

  private static JSONValue parse(String jsonString, boolean strict) {
    if (jsonString == null) {
      throw new NullPointerException();
    }
    if (jsonString.length() == 0) {
      throw new IllegalArgumentException("empty argument");
    }
    try {
      return evaluate(jsonString, strict);
    } catch (JavaScriptException ex) {
      throw new JSONException(ex);
    }
  }

  /**
   * Not instantiable.
   */
  private JSONParser() {
  }
}
