/*
 * 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.
 */
/* Header file */
#include <stdio.h>
#include "js-objectadapter.h"
#include "js-scriptruntime.h"
#include "js-utils.h"
#include "js-nativeerror.h"

/* Internal data */
const jsString_t JSNativeError::className = "Error";

/* Procedures */
void JSNativeError::finishInit(JSContext * cx, JSScriptable * scope, JSFunctionObject * ctor, JSScriptable * proto)
{
    class ErrorAdapter:public JSObjectAdapter {
      public:
        JS_OA_DefineFunction(toString, JSNativeError)
    };
    static jsFunction_t functions[] = {
#define ItemAdapter(name, clazz, length)      { #name,  &clazz::name, length }
        ItemAdapter(toString, ErrorAdapter, 0),
#undef  ItemAdapter
    };

    ((JSScriptableObject *) proto)->defineFunctionProperties(cx, className, TableSize(functions), functions, JS_PA_DontEnum);

    ((JSScriptableObject *) proto)->defineProperty(cx, "message", JS_STRING_TO_VAL(JS_NewGCString(cx, "")), JS_PA_Null);
    ((JSScriptableObject *) proto)->defineProperty(cx, "name", JS_STRING_TO_VAL(JS_NewGCString(cx, "Error")), JS_PA_Null);
}
jsVal_t JSNativeError::jsConstructor(JSContext * cx, int numArgs, jsVal_t * args, JSFunction * ctorObj, jsBool_t inNewExpr)
{
    return JS_OBJECT_TO_VAL(new(cx) JSNativeError());
}

void JSNativeError::defineClass(JSContext * cx, JSScriptable * scope)
{
    JSScriptable *proto = new(cx) JSNativeError();

    JSScriptableObject::defineClass(cx, scope, proto, jsConstructor, finishInit);
}

jsVal_t JSNativeError::jsFunction_toString(JSContext * cx)
{
    jsString_t s = toString(cx);
    jsVal_t result = JS_STRING_TO_VAL(JS_NewGCString(cx, s));

    JS_DeleteZoneObj(cx, s);
    return result;
}

jsString_t JSNativeError::toString(JSContext * cx)
{
    jsString_t name = getName(cx);
    jsString_t message = getMessage(cx);

    int length = strlen(name) + strlen(message) + TableSize(": ") - 1;
    jsString_t string = (jsString_t) JS_NewZoneObj(cx,
            sizeof(*string) * length + 1);

    sprintf(string, "%s: %s", name, message);

    JS_DeleteZoneObj(cx, message);
    JS_DeleteZoneObj(cx, name);

    return string;
}

jsString_t JSNativeError::getName(JSContext * cx)
{
    return JSScriptRuntime::toString(cx, JSScriptRuntime::getProp(cx, JS_OBJECT_TO_VAL(this), "name", this));
}

jsString_t JSNativeError::getMessage(JSContext * cx)
{
    return JSScriptRuntime::toString(cx, JSScriptRuntime::getProp(cx, JS_OBJECT_TO_VAL(this), "message", this));
}

jsBool_t JSNativeError::isInstanceOf(const jsString_t className)
{
    if (className == JSNativeError::className)
        return TRUE;
    return JSScriptableObject::isInstanceOf(className);
}

jsString_t JSNativeError::getClassName(JSContext * cx)
{
    return className;
}
