#ifndef _H_NPVariantWrapper
#define _H_NPVariantWrapper

#include <string>
#include <ostream>

#ifdef sun
// Sun's cstring doesn't define strlen/etc
#include <string.h>
#endif
#include <cstring>
#include <stdio.h>

#include "Debug.h"
#include "Platform.h"

#include "mozincludes.h"

#include "Value.h"
#include "LocalObjectTable.h"
#include "Plugin.h"
#include "JavaObject.h"

/**
 * Contains NPVariantProxy, NPVariantWrapper, and NPVariantArray
 */

/**
 * Wraps an NPVariant and provides various conversion functions.  The variant
 * provided retained at create time.
 */
class NPVariantProxy {
  friend class NPVariantArray;
private:
  ScriptableInstance& plugin;
  NPVariant& variant;
public:
  NPVariantProxy(ScriptableInstance& plugin, NPVariant& variant)
      : plugin(plugin), variant(variant)
  {
    VOID_TO_NPVARIANT(variant);
  }
  
  NPVariantProxy(ScriptableInstance& plugin, NPVariant& variant, bool noinit)
      : plugin(plugin), variant(variant)
  {
  }

  ~NPVariantProxy() {
  }
  
  operator NPVariant() const {
    return variant;
  }
  
  const NPVariant* operator->() const {
	return &variant;
  }

  const NPVariant* address() const {
    return &variant;
  }

  int isBoolean() const {
    return isBoolean(variant);
  }

  static int isBoolean(const NPVariant& variant) {
    return NPVARIANT_IS_BOOLEAN(variant);
  }

  bool getAsBoolean() const {
    return getAsBoolean(variant);
  }

  static bool getAsBoolean(const NPVariant& variant) {
    return NPVARIANT_TO_BOOLEAN(variant);
  }

  int isInt() const {
    return isInt(variant);
  }
  
  // Return true if the variant is holding a regular integer or an integral double.
  static int isInt(const NPVariant& variant) {
    if (NPVARIANT_IS_INT32(variant)) {
      return 1;
    } else if (NPVARIANT_IS_DOUBLE(variant)) {
      // As of http://trac.webkit.org/changeset/72974 we get doubles for all
      // numerical variants out of V8.
      double d = NPVARIANT_TO_DOUBLE(variant);
      int i = static_cast<int>(d);
      // Verify that d is an integral value in range.
      return (d == static_cast<double>(i));
    } else {
      return 0;
    }
  }

  int getAsInt() const {
    return getAsInt(variant);
  }

  static int getAsInt(const NPVariant& variant) {
    if (isInt(variant)) {
      if (NPVARIANT_IS_INT32(variant)) {
        return NPVARIANT_TO_INT32(variant);
      } else if (NPVARIANT_IS_DOUBLE(variant)) {
        return static_cast<int>(NPVARIANT_TO_DOUBLE(variant));
      }
    }

    Debug::log(Debug::Error) << "getAsInt: variant " <<
      NPVariantProxy::toString(variant) << "not int" << Debug::flush;
    return 0;
  }

  int isNull() const {
    return isNull(variant);
  }
  
  static int isNull(const NPVariant& variant) {
    return NPVARIANT_IS_NULL(variant);
  }

  int isObject() const {
    return isObject(variant);
  }
  
  static int isObject(const NPVariant& variant) {
    return NPVARIANT_IS_OBJECT(variant);
  }

  NPObject* getAsObject() const {
    return getAsObject(variant);
  }

  static NPObject* getAsObject(const NPVariant& variant) {
    if (NPVARIANT_IS_OBJECT(variant)) {
      return NPVARIANT_TO_OBJECT(variant);
    }
    Debug::log(Debug::Error) << "getAsObject: variant not object" << Debug::flush;
    return 0;
  }

  int isString() const {
    return isString(variant);
  }
  
  static int isString(const NPVariant& variant) {
    return NPVARIANT_IS_STRING(variant);
  }

  const NPString* getAsNPString() const {
    return getAsNPString(variant);
  }

  static const NPString* getAsNPString(const NPVariant& variant) {
    if (NPVARIANT_IS_STRING(variant)) {
      return &NPVARIANT_TO_STRING(variant);
    }
    Debug::log(Debug::Error) << "getAsNPString: variant not string" << Debug::flush;
    return 0;
  }

  Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const {
    return getAsValue(variant, scriptInstance, unwrapJava);
  }

  static Value getAsValue(const NPVariant& variant, ScriptableInstance& scriptInstance,
      bool unwrapJava = true) {
    Value val;
    if (NPVARIANT_IS_VOID(variant)) {
      val.setUndefined();
    } else if (NPVARIANT_IS_NULL(variant)) {
      val.setNull();
    } else if (NPVARIANT_IS_BOOLEAN(variant)) {
      val.setBoolean(NPVARIANT_TO_BOOLEAN(variant));
    } else if (NPVARIANT_IS_INT32(variant)) {
      val.setInt(NPVARIANT_TO_INT32(variant));      
    } else if (NPVARIANT_IS_DOUBLE(variant)) {
      val.setDouble(NPVARIANT_TO_DOUBLE(variant));
    } else if (NPVARIANT_IS_STRING(variant)) {
      NPString str = NPVARIANT_TO_STRING(variant);
      val.setString(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
    } else if (NPVARIANT_IS_OBJECT(variant)) {
      NPObject* obj = NPVARIANT_TO_OBJECT(variant);
      if (unwrapJava && JavaObject::isInstance(obj)) {
        JavaObject* jObj = static_cast<JavaObject*>(obj);
        val.setJavaObject(jObj->getObjectId());
      } else {
        NPVariant result;
        VOID_TO_NPVARIANT(result);
        if (scriptInstance.tryGetStringPrimitive(obj, result)) {
          NPString str = NPVARIANT_TO_STRING(result);
          val.setString(GetNPStringUTF8Characters(str), GetNPStringUTF8Length(str));
          release(result);
        } else {
          val.setJsObjectId(scriptInstance.getLocalObjectRef(obj));
        }
      }
    } else {
      Debug::log(Debug::Error) << "Unsupported NPVariant type " << variant.type << Debug::flush;
    }
    return val;
  }
  
  /**
   * The incoming variant is not altered, and is not even required to have
   * its contents retained.  Any object will get an extra refcount on it
   * when copied to this variant, and strings will be copied.
   */
  NPVariantProxy& operator=(const NPVariant& newval) {
    assignFrom(variant, newval);
    return *this;
  }

  /**
   * The incoming variant is not altered, and is not even required to have
   * its contents retained.  Any object will get an extra refcount on it
   * when copied to this variant, and strings will be copied.
   */
  static void assignFrom(NPVariant& variant, const NPVariant& newval) {
    release(variant);
    variant = newval;
    if (NPVARIANT_IS_STRING(newval)) {
      int n = variant.value.stringValue.UTF8Length;
      char* strBytes = reinterpret_cast<char*>(NPN_MemAlloc(n));
      memcpy(strBytes, variant.value.stringValue.UTF8Characters, n);
      variant.value.stringValue.UTF8Characters = strBytes;
    } else {
      retain(variant);
    }
  }

  NPVariantProxy& operator=(NPObject* obj) {
    assignFrom(variant, obj);
    return *this;
  }
  
  static void assignFrom(NPVariant& variant, NPObject* obj) {
    release(variant);
    OBJECT_TO_NPVARIANT(obj, variant);
    retain(variant);
  }

  // Convenience method for C++ code
  NPVariantProxy& operator=(int intVal) {
    assignFrom(variant, intVal);
    return *this;
  }

  // Convenience method for C++ code
  static void assignFrom(NPVariant& variant, int intVal) {
    NPVariant newvar;
    INT32_TO_NPVARIANT(intVal, newvar);
    assignFrom(variant, newvar);
  }

  // Convenience method for C++ code
  NPVariantProxy& operator=(const std::string& strval) {
    assignFrom(variant, strval);
    return *this;
  }

  // Convenience method for C++ code
  static void assignFrom(NPVariant& variant, const std::string& strval) {
    NPVariant newvar;
    STDSTRING_TO_NPVARIANT(strval, newvar);
    assignFrom(variant, newvar);
  }
  
  // Convenience method for C++ code
  NPVariantProxy& operator=(const char* strval) {
    assignFrom(variant, strval);
    return *this;
  }

  // Convenience method for C++ code
  static void assignFrom(NPVariant& variant, const char* strval) {
    NPVariant newvar;
    STRINGZ_TO_NPVARIANT(strval, newvar);
    assignFrom(variant, newvar);
  }

  NPVariantProxy& operator=(const Value& newval) {
    assignFrom(plugin, variant, newval);
    return *this;
  }

  static void assignFrom(ScriptableInstance& plugin, NPVariant& variant, const Value& newval) {
    NPVariant newvar;
    VOID_TO_NPVARIANT(newvar);
    if (newval.isBoolean()) {
      BOOLEAN_TO_NPVARIANT(newval.getBoolean(), newvar);
    } else if (newval.isByte()) {
      INT32_TO_NPVARIANT(newval.getByte(), newvar);
    } else if (newval.isChar()) {
      INT32_TO_NPVARIANT(newval.getChar(), newvar);
    } else if (newval.isShort()) {
      INT32_TO_NPVARIANT(newval.getShort(), newvar);
    } else if (newval.isInt()) {
      int value = newval.getInt();
      // Firefox NPAPI bug: 32-bit ints get mapped to int jsvals, regardless of range.
      // However, int jsvals are 31 bits, so we need to use a double if the value is
      // not representable in a 31 bit signed 2's-complement value.
      if (value >= 0x40000000 || value < -0x40000000) {
        DOUBLE_TO_NPVARIANT(static_cast<double>(value), newvar);
      } else {
        INT32_TO_NPVARIANT(value, newvar);
      }
    } else if (newval.isFloat()) {
      DOUBLE_TO_NPVARIANT(newval.getFloat(), newvar);
    } else if (newval.isDouble()) {
      DOUBLE_TO_NPVARIANT(newval.getDouble(), newvar);
    } else if (newval.isNull()) {
      NULL_TO_NPVARIANT(newvar);
    } else if (newval.isUndefined()) {
      VOID_TO_NPVARIANT(newvar);
    } else if (newval.isString()) {
      assignFrom(variant, newval.getString());
      return;
    } else if (newval.isJavaObject()) {
      if (1) {
        JavaObject* jObj = plugin.createJavaWrapper(newval.getJavaObjectId());
        NPObject* obj = jObj;
        OBJECT_TO_NPVARIANT(obj, newvar);
      } else {
        VOID_TO_NPVARIANT(newvar);
      }
    } else if (newval.isJsObject()) {
      OBJECT_TO_NPVARIANT(plugin.getLocalObject(newval.getJsObjectId()),
    	  newvar);
    } else {
      Debug::log(Debug::Error) << "Unsupported NPVariant type " << newval.getType() << Debug::flush;
    }
    assignFrom(variant, newvar);
  }

  std::string toString() const {
    return toString(variant);
  }

  static std::string toString(const NPVariant& variant) {
    std::string retval;
    // TODO(jat): remove sprintfs
    char buf[40];
    NPObject* npObj;
    switch (variant.type) {
      case NPVariantType_Void:
        retval = "undef";
        break;
      case NPVariantType_Null:
        retval = "null";
        break;
      case NPVariantType_Bool:
        retval = "bool(";
        retval += (NPVARIANT_TO_BOOLEAN(variant) ? "true" : "false");
        retval += ')';
        break;
      case NPVariantType_Int32:
        retval = "int(";
        snprintf(buf, sizeof(buf), "%d)", NPVARIANT_TO_INT32(variant));
        retval += buf;
        break;
      case NPVariantType_Double:
        retval = "double(";
        snprintf(buf, sizeof(buf), "%g)", NPVARIANT_TO_DOUBLE(variant));
        retval += buf;
        break;
      case NPVariantType_String:
        {
          retval = "string(";
          NPString str = NPVARIANT_TO_STRING(variant);
          retval += std::string(str.UTF8Characters, str.UTF8Length);
          retval += ')';
        }
        break;
      case NPVariantType_Object:
        npObj = NPVARIANT_TO_OBJECT(variant);
        if (JavaObject::isInstance(npObj)) {
          JavaObject* javaObj = static_cast<JavaObject*>(npObj);
          snprintf(buf, sizeof(buf), "javaObj(id=%d, ", javaObj->getObjectId());
        } else {
          snprintf(buf, sizeof(buf), "jsObj(class=%p, ", npObj->_class);
        }
        retval = buf;
        snprintf(buf, sizeof(buf), "%p)", npObj);
        retval += buf;
        break;
      default:
        snprintf(buf, sizeof(buf), "Unknown type %d", variant.type);
        retval = buf;
        break;
    }
    return retval;
  }

public:
  void release() {
    release(variant);
  }

  static void release(NPVariant& variant) {
    NPN_ReleaseVariantValue(&variant);
  }

  void retain() {
    retain(variant);
  }

  static void retain(NPVariant& variant) {
    if (NPVARIANT_IS_OBJECT(variant)) {
      NPN_RetainObject(NPVARIANT_TO_OBJECT(variant));
    }
  }
};

inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariant& var) {
  return dbg << NPVariantProxy::toString(var);
}

inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantProxy& var) {
  return dbg << var.toString();
}

/**
 * Variation of NPVariantProxy that provides its own variant and always frees it
 * when the wrapper goes away.
 */
class NPVariantWrapper  {
private:
  ScriptableInstance& plugin;
  NPVariant variant;
public:
  NPVariantWrapper(ScriptableInstance& plugin) : plugin(plugin) {
    VOID_TO_NPVARIANT(variant);
  }

  ~NPVariantWrapper() {
    release();
  }

  operator NPVariant() const {
    return variant;
  }

  const NPVariant* operator->() const {
  return &variant;
  }

  const NPVariant* address() const {
    return &variant;
  }

  /**
   * Get the address for use as a return value.  Since the value can be trashed,
   * we need to release any data we currently hold.
   */
  NPVariant* addressForReturn() {
    NPVariantProxy::release(variant);
    VOID_TO_NPVARIANT(variant);
    NPVariantProxy::retain(variant); // does nothing, present for consistency
    return &variant;
  }
  
  bool isBoolean() const {
    return NPVariantProxy::isBoolean(variant);
  }

  int isInt() const {
    return NPVariantProxy::isInt(variant);
  }
  
  int isObject() const {
    return NPVariantProxy::isObject(variant);
  }
  
  int isString() const {
    return NPVariantProxy::isString(variant);
  }
  
  bool getAsBoolean() const {
    return NPVariantProxy::getAsBoolean(variant);
  }

  int getAsInt() const {
    return NPVariantProxy::getAsInt(variant);
  }

  NPObject* getAsObject() const {
    return NPVariantProxy::getAsObject(variant);
  }

  const NPString* getAsNPString() const {
    return NPVariantProxy::getAsNPString(variant);
  }

  Value getAsValue(ScriptableInstance& scriptInstance, bool unwrapJava = true) const {
    return NPVariantProxy::getAsValue(variant, scriptInstance, unwrapJava);
  }

  /**
   * The incoming variant is not altered, and is not even required to have
   * its contents retained.  Any object will get an extra refcount on it
   * when copied to this variant, and strings will be copied.
   */
  NPVariantWrapper& operator=(const NPVariant& newval) {
    NPVariantProxy::assignFrom(variant, newval);
    return *this;
  }

  NPVariantWrapper& operator=(const Value& newval) {
    NPVariantProxy::assignFrom(plugin, variant, newval);
    return *this;
  }
  
  NPVariantWrapper& operator=(NPObject* obj) {
    NPVariantProxy::assignFrom(variant, obj);
    return *this;
  }
  
  // Convenience method for C++ code
  NPVariantWrapper& operator=(const std::string& strval) {
    NPVariantProxy::assignFrom(variant, strval);
    return *this;
  }

  // Convenience method for C++ code
  NPVariantWrapper& operator=(const char* strval) {
    NPVariantProxy::assignFrom(variant, strval);
    return *this;
  }

  // Convenience method for C++ code
  NPVariantWrapper& operator=(int intval) {
    NPVariantProxy::assignFrom(variant, intval);
    return *this;
  }

  void release() {
    NPVariantProxy::release(variant);
  }

  void retain() {
    NPVariantProxy::retain(variant);
  }

  std::string toString() const {
    return NPVariantProxy::toString(variant);
  }
};

inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantWrapper& var) {
  dbg << var.toString();
  return dbg;
}

/**
 * Maintains an array of NPVariants and cleans them up when it is destroyed.
 */
class NPVariantArray {
private:
	ScriptableInstance& plugin;
  int size;
  NPVariant* args;

public:
  NPVariantArray(ScriptableInstance& plugin, int size) : plugin(plugin), size(size) {
    args = new NPVariant[size];
    for (int i = 0; i < size; ++i) {
      VOID_TO_NPVARIANT(args[i]);
    }
  }

  ~NPVariantArray() {
    for (int i = 0; i < size; ++i) {
      NPN_ReleaseVariantValue(&args[i]);
    }
    delete [] args;
  }

  const NPVariant* getArray() const {
    return args;
  }

  int getSize() const {
    return size;
  }

  const NPVariant& operator[](int idx) const {
    if (idx >= size) {
      printf("NPVariantArray[idx=%d] const: size=%d\n", idx, size);
    }
    return args[idx];
  }

  NPVariantProxy operator[](int idx) {
    if (idx >= size) {
      printf("NPVariantArray[idx=%d]: size=%d\n", idx, size);
    }
    return NPVariantProxy(plugin, args[idx], true);
  }
};

inline Debug::DebugStream& operator<<(Debug::DebugStream& dbg, const NPVariantArray& var) {
  dbg << "[";
  for (int i = 0; i < var.getSize(); ++i) {
    dbg << " " << var[i]; 
  }
  dbg << " ]";
  return dbg;
}

#endif
