#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 isInt() const {
    return isInt(variant);
  }
  
  static int isInt(const NPVariant& variant) {
    return NPVARIANT_IS_INT32(variant);
  }

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

  static int getAsInt(const NPVariant& variant) {
    if (NPVARIANT_IS_INT32(variant)) {
      return NPVARIANT_TO_INT32(variant);
    }
    Debug::log(Debug::Error) << "getAsInt: 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;
  }

  int isInt() const {
    return NPVariantProxy::isInt(variant);
  }
  
  int isObject() const {
    return NPVariantProxy::isObject(variant);
  }
  
  int isString() const {
    return NPVariantProxy::isString(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
