/*
 * The contents of this file are subject to the Netscape Public
 * License Version 1.1 (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.mozilla.org/NPL/

 * Software distributed under the License is distributed on an "AS
 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
 * implied. See the License for the specific language governing
 * rights and limitations under the License.

 * The Original Code is Rhino code, released
 * May 6, 1999.

 * The Initial Developer of the Original Code is Netscape
 * Communications Corporation.  Portions created by Netscape are
 * Copyright (C) 1997-1999 Netscape Communications Corporation. All
 * Rights Reserved.

 * Contributor(s): 

 * Alternatively, the contents of this file may be used under the
 * terms of the GNU Public License (the "GPL"), in which case the
 * provisions of the GPL are applicable instead of those above.
 * If you wish to allow use of your version of this file only
 * under the terms of the GPL and not to allow others to use your
 * version of this file under the NPL, indicate your decision by
 * deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL.  If you do not delete
 * the provisions above, a recipient may use your version of this
 * file under either the NPL or the GPL.
 */
/*
 *  JavaScript Interpreter
 *  The JavaScript Interpreter is used for executing JavaScript programs
 *  in EWB that control user events on buttons, restrict inputs on textlines
 *  and so on.
 *
 *  Developmened by: Institute of Artificial Intelligence & Robotics
 *                   of Xi'an Jiaotong University
 *
 *  Create by:      Tian Wenqiang
 *  Last modified:  2001-11-13 19:56
 */

/* JS host object class implement file */
#include "js-scriptruntime.h"
#include "js-nativehost.h"
#ifndef SHELL
extern "C" {
# include "ewb-trace.h"
}
#endif

/* Class data */
const jsString_t	JSNativeHost::className = "NativeHost";

/* Procedures */
jsClass_t *
JSNativeHost::defaultClass()
{
    class DefaultClass {
 	public:
	    static jsString_t
			getClassName(jsContext_t context, jsObject_t object) {

		return JSNativeHost::className;
	    }
	    static jsBool_t
			has(jsContext_t context, jsObject_t object,
				jsString_t name, jsObject_t start) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::has(cx, name, _start);
	    }
	    static jsBool_t
			get(jsContext_t context, jsObject_t object, 
				jsString_t name, jsObject_t start,
				jsVal_t *value) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::get(cx, name, _start, value);
	    }
	    static void	put(jsContext_t context, jsObject_t object, 
				jsString_t name, jsObject_t start,
				jsVal_t value) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		((JSNativeHost *) _object)
			->JSScriptableObject::put(cx, name, _start, value);
	    }
	    static void	del(jsContext_t context, jsObject_t object,
				jsString_t name) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		((JSNativeHost *) _object)->JSScriptableObject::del(cx, name);
	    }
	    static jsBool_t
			has(jsContext_t context, jsObject_t object,
				int index, jsObject_t start) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::has(cx, index, _start);
	    }
	    static jsBool_t
			get(jsContext_t context, jsObject_t object,
				int index, jsObject_t start, jsVal_t *value) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::get(cx, index, _start, value);
	    }
	    static void	put(jsContext_t context, jsObject_t object,
				int index, jsObject_t start, jsVal_t value) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_start = (JSScriptable *) start;

		((JSNativeHost *) _object)
			->JSScriptableObject::put(cx, index, _start, value);
	    }
	    static void	del(jsContext_t context, jsObject_t object,
				int index) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		((JSNativeHost *) _object)
			->JSScriptableObject::del(cx, index);

	    }
	    static jsObject_t
			getPrototype(jsContext_t context, jsObject_t object) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		return ((JSNativeHost *) _object)
				->JSScriptableObject::getPrototype(cx);
	    }
	    static void	setPrototype(jsContext_t context, jsObject_t object,
				jsObject_t proto) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_proto = (JSScriptable *) proto;

		((JSNativeHost *) _object)
			->JSScriptableObject::setPrototype(cx, _proto);
	    }
	    static jsObject_t
			getParentScope(jsContext_t context, jsObject_t object) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::getParentScope(cx);
	    }
	    static void	setParentScope(jsContext_t context, jsObject_t object,
				jsObject_t parent) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_parent = (JSScriptable *) parent;

		((JSNativeHost *) _object)
			->JSScriptableObject::setParentScope(cx, _parent);
	    }
	    static jsVal_t *
			getIds(jsContext_t context, jsObject_t object,
				int *numIds) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::getIds(cx, numIds);
	    }
	    static jsVal_t
			getDefaultValue(jsContext_t context, jsObject_t object,
				jsType_t hint) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::getDefaultValue(cx, hint);
	    }
	    static jsBool_t
			hasInstance(jsContext_t context, jsObject_t object,
				jsObject_t instance) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;
		JSScriptable *_instance = (JSScriptable *) object;

		return ((JSNativeHost *) _object)
			->JSScriptableObject::hasInstance(cx, _instance);
	    }
	    static void	finalize(jsContext_t context, jsObject_t object) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		((JSNativeHost *) _object)
			->JSScriptableObject::finalize(cx);
	    }
	    static void	mark(jsContext_t context, jsObject_t object) {
		JSContext *cx = (JSContext *) context;
		JSScriptable *_object = (JSScriptable *) object;

		((JSNativeHost *) _object)
			->JSScriptableObject::mark(cx);
	    }

    } ;
    static jsClass_t clazz =  {
	&DefaultClass::getClassName,
	&DefaultClass::has,
	&DefaultClass::get,
	&DefaultClass::put,
	&DefaultClass::del,
	&DefaultClass::has,
	&DefaultClass::get,
	&DefaultClass::put,
	&DefaultClass::del,
	&DefaultClass::getPrototype,
	&DefaultClass::setPrototype,
	&DefaultClass::getParentScope,
	&DefaultClass::setParentScope,
	&DefaultClass::getIds,
	&DefaultClass::getDefaultValue,
	&DefaultClass::hasInstance,
	&DefaultClass::finalize,
	&DefaultClass::mark,
    } ;

    return &clazz;
}
void *
JSNativeHost::getClosure()
{
    return closure;
}
void
JSNativeHost::setClosure(void *closure)
{
    this->closure = closure;
}
jsBool_t
JSNativeHost::isInstanceOf(const jsString_t className)
{
    if (className == JSNativeHost::className) return TRUE;
    return JSScriptableObject::isInstanceOf(className);
}
jsString_t
JSNativeHost::getClassName(JSContext *cx)
{
    return clazz->getClassName((jsContext_t) cx, (jsObject_t) this);
}
jsBool_t
JSNativeHost::get(JSContext *cx, jsString_t name, JSScriptable *start,
		jsVal_t *value)
{
	jsBool_t	ret;

#ifndef SHELL
EWBTPENT(11,"JsSerch");
#endif

	ret = clazz->get((jsContext_t) cx, (jsObject_t) this, name,
			(jsObject_t) start, value);

#ifndef SHELL
EWBTPEXT(11);
#endif

    return ret;
}
jsBool_t
JSNativeHost::get(JSContext *cx, int index, JSScriptable *start, jsVal_t *value)
{
    return clazz->getIndex((jsContext_t) cx, (jsObject_t) this, index,
			(jsObject_t) start, value);
}
jsBool_t
JSNativeHost::has(JSContext *cx, jsString_t name, JSScriptable *start)
{
	jsBool_t	ret;

#ifndef SHELL
EWBTPENT(11,"JsSerch");
#endif

    ret = clazz->has((jsContext_t) cx, (jsObject_t) this, name,
		(jsObject_t) start);

#ifndef SHELL
EWBTPEXT(11);
#endif

	return ret;
}
jsBool_t
JSNativeHost::has(JSContext *cx, int index, JSScriptable *start)
{
    return clazz->hasIndex((jsContext_t) cx, (jsObject_t) this, index,
			(jsObject_t) start);
}

void
JSNativeHost::put(JSContext *cx, jsString_t name, JSScriptable *start, jsVal_t value)
{

#ifndef SHELL
EWBTPENT(11,"JsSerch");
#endif

    clazz->put((jsContext_t) cx, (jsObject_t) this, name, (jsObject_t) start, value);

#ifndef SHELL
EWBTPEXT(11);
#endif

}

void
JSNativeHost::put(JSContext *cx, int index, JSScriptable *start, jsVal_t value)
{
    clazz->putIndex((jsContext_t) cx, (jsObject_t) this, index,
		(jsObject_t) start, value);
}

void
JSNativeHost::del(JSContext *cx, jsString_t name)
{
    clazz->del((jsContext_t) cx, (jsObject_t) this, name);
}
void
JSNativeHost::del(JSContext *cx, int index )
{
    clazz->delIndex((jsContext_t) cx, (jsObject_t) this, index);
}
JSScriptable *
JSNativeHost::getPrototype(JSContext *cx)
{
    return (JSScriptable *) clazz
		->getPrototype((jsContext_t) cx, (jsObject_t) this); 
}
void
JSNativeHost::setPrototype(JSContext *cx, JSScriptable *prototype)
{
    clazz->setPrototype(
		(jsContext_t) cx, (jsObject_t) this, (jsObject_t) prototype); 
}
JSScriptable *
JSNativeHost::getParentScope(JSContext *cx)
{
    return (JSScriptable *) clazz
		->getParentScope((jsContext_t) cx, (jsObject_t) this);
}
void
JSNativeHost::setParentScope(JSContext *cx, JSScriptable *parent)
{
    clazz->setParentScope(
		(jsContext_t) cx, (jsObject_t) this, (jsObject_t) parent); 
}
jsVal_t *
JSNativeHost::getIds(JSContext *cx, int *numIds)
{
    return clazz->getIds((jsContext_t) cx, (jsObject_t) this, numIds);
}
jsVal_t
JSNativeHost::getDefaultValue(JSContext *cx, jsType_t hint)
{
    return clazz->getDefaultValue((jsContext_t) cx, (jsObject_t) this, hint);
}
jsBool_t
JSNativeHost::hasInstance(JSContext *cx, JSScriptable *instance)
{
    return clazz->hasInstance((jsContext_t) cx, (jsObject_t) this,
			(jsObject_t) instance);
}
jsVal_t
JSNativeHost::call(JSContext *cx, JSScriptable *scope, JSScriptable *thisObj,
		int numArgs, jsVal_t *args)
{
    if (numArgs > 0) {
	return JSScriptRuntime::getElem(cx, JS_OBJECT_TO_VAL(this), 
					args[0], scope);
    }
    return JS_VAL_VOID;
}
JSScriptable *
JSNativeHost::construct(JSContext *cx, JSScriptable *scope, int numArgs,
			jsVal_t *args)
{
    return NULL;
}
void
JSNativeHost::mark(JSContext *cx)
{
    JSGCHeap *gcHeap = &cx->runtime->gcHeap;

    if (gcHeap->isMarkObj(this)) return;

    JSScriptableObject::mark(cx);
    if ( clazz->mark != NULL ) {
    	clazz->mark((jsContext_t) cx, (jsObject_t) this);
    }
}
void
JSNativeHost::finalize(JSContext *cx)
{
    clazz->finalize((jsContext_t) cx, (jsObject_t) this);
}

JSNativeHost::JSNativeHost(jsClass_t *clazz)
{
    this->clazz = clazz;
    closure = NULL;   
}
JSNativeHost::JSNativeHost(JSScriptable *proto)
{
    clazz = proto != NULL ? ((JSNativeHost *) proto)->clazz : defaultClass();
    closure = NULL;   
}

