/*
 * 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.
 */
#ifdef NATIVE_DEBUG
/* Header file */
#include <stdio.h>
#ifdef VX
#include <vxWorks.h>
#include <taskLib.h>
#include <stdio.h>
#endif
#include "js-new.h"
#include "js-scriptruntime.h"
#include "js-exceptionhandler.h"
#include "js-scriptableobject.h"
#include "js-api.h"
#include "js-nativedebug.h"
#ifndef SHELL
extern "C" {
# include "ewb-trace.h"
}
#endif
#include "js-frame.h"
#include "js-interpreterdata.h"

/* Class data */
const jsString_t	JSNativeDebug::className = "Debug";

/* Procedures */
/**
 * Print the string values of its arguments.
 *
 * This method is defined as a JavaScript function.
 * Note that its arguments are of the "varargs" form, which
 * allows it to handle an arbitrary number of arguments
 * supplied to the JavaScript function.
 *
 */
#ifdef WEBUI
#include	"ewb-sys-if.h"
extern "C" void		EwbSetServerLog(int id, void * data);
#endif
#ifndef SHELL
extern  int             ewbPrintOn;
#endif

jsVal_t
JSNativeDebug::print(JSContext *cx, JSScriptable *thisObj,
		int numArgs, jsVal_t *args, JSFunction *funObj)
{
    char      buff[181];
    buff[0] = '\0';

    for (int i = 0; i < numArgs; i++) {
        if (i > 0) {
	    strncat(buff," ",sizeof(buff)-strlen(buff)-1);
            //printf(" ");
	}

        // Convert the arbitrary JavaScript value into a string form.
        jsString_t s = cx->toString(args[i]);
	strncat(buff,s,sizeof(buff)-strlen(buff)-1);
        //printf("%s", s);
    }
    //printf("\n");
    strncat(buff,"\n",sizeof(buff)-strlen(buff)-1);
#ifdef WEBUI
    EwbSetServerLog(EWB_LOG_INFO, buff);
#endif
#ifndef SHELL
    if (ewbPrintOn) {
	printf("[Info]%s",buff);
    }
#endif
    return JS_VAL_VOID;
}

jsVal_t
JSNativeDebug::printdbg(JSContext *cx, JSScriptable *thisObj,
        int numArgs, jsVal_t *args, JSFunction *funObj)
{
    char      buff[181];
    buff[0] = '\0';

    for (int i = 0; i < numArgs; i++) {
        if (i > 0) {
        strncat(buff," ",sizeof(buff)-strlen(buff)-1);
            //printf(" ");
    }

        // Convert the arbitrary JavaScript value into a string form.
        jsString_t s = cx->toString(args[i]);
    strncat(buff,s,sizeof(buff)-strlen(buff)-1);
        //printf("%s", s);
    }
    //printf("\n");
    strncat(buff,"\n",sizeof(buff)-strlen(buff)-1);
#ifdef WEBUI
    EwbSetServerLog(EWB_LOG_DEBUG, buff);
#endif
#ifndef SHELL
    if (ewbPrintOn) {
    printf("[Debug]%s",buff);
    }
#endif
    return JS_VAL_VOID;
}

jsVal_t
JSNativeDebug::printwarn(JSContext *cx, JSScriptable *thisObj,
        int numArgs, jsVal_t *args, JSFunction *funObj)
{
    char      buff[181];
    buff[0] = '\0';

    for (int i = 0; i < numArgs; i++) {
        if (i > 0) {
        strncat(buff," ",sizeof(buff)-strlen(buff)-1);
            //printf(" ");
    }

        // Convert the arbitrary JavaScript value into a string form.
        jsString_t s = cx->toString(args[i]);
    strncat(buff,s,sizeof(buff)-strlen(buff)-1);
        //printf("%s", s);
    }
    //printf("\n");
    strncat(buff,"\n",sizeof(buff)-strlen(buff)-1);
#ifdef WEBUI
    EwbSetServerLog(EWB_LOG_WARN, buff);
#endif
#ifndef SHELL
    if (ewbPrintOn) {
    printf("[Warn]%s",buff);
    }
#endif
    return JS_VAL_VOID;
}

jsVal_t
JSNativeDebug::printerr(JSContext *cx, JSScriptable *thisObj,
        int numArgs, jsVal_t *args, JSFunction *funObj)
{
    char      buff[181];
    buff[0] = '\0';

    for (int i = 0; i < numArgs; i++) {
        if (i > 0) {
        strncat(buff," ",sizeof(buff)-strlen(buff)-1);
            //printf(" ");
    }

        // Convert the arbitrary JavaScript value into a string form.
        jsString_t s = cx->toString(args[i]);
    strncat(buff,s,sizeof(buff)-strlen(buff)-1);
        //printf("%s", s);
    }
    //printf("\n");
    strncat(buff,"\n",sizeof(buff)-strlen(buff)-1);
#ifdef WEBUI
    EwbSetServerLog(EWB_LOG_ERROR, buff);
#endif
#ifndef SHELL
    if (ewbPrintOn) {
    printf("[Err]%s",buff);
    }
#endif
    return JS_VAL_VOID;
}

jsVal_t
JSNativeDebug::trace(JSContext *cx, JSScriptable *thisObj,
		int numArgs, jsVal_t *args, JSFunction *funObj)
{
    if( numArgs > 0 ) {
 
    // Convert the arbitrary JavaScript value into a string form.
#ifndef SHELL
# ifdef EWB_DEBUG
    jsString_t s = cx->toString(args[0]);

    EWBTIME("*trace*",(char*)s);
# endif
#endif

//	printf("%s\n", s);
    }
    return JS_VAL_VOID;
}

jsVal_t
JSNativeDebug::where(JSContext *cx, JSScriptable *thisObj,
		int numArgs, jsVal_t *args, JSFunction *funObj)
{
    int i=0;
    JSFrame *a;
    a = (JSFrame *) lstLast(&(cx->frames));

    while(1){
	if((a->theData->itsName != NULL)){
	    printf("#%d %s at %s\n"
		   ,i,(a->theData->itsName),(a->theData->itsSourceFile));
	}else{
	    printf("NULL \n");
	}
	    
	if(lstPrevious((NODE*)a) != NULL){
	    a = (JSFrame *) lstPrevious((NODE*)a);
	}else{
	    break;
	}
	i++;
    }
    return JS_VAL_VOID;
}

void
JSNativeDebug::defineClass(JSContext *cx, JSScriptable *scope)
{
    class DebugAdapter {
        public: 
            static jsVal_t      jsFunction_gc(JSContext *cx,
                                        JSScriptable *thisObj, int numArgs,
                                        jsVal_t *args, JSFunction *funObj) {
                JSNativeDebug::gc(cx);
		return JS_VAL_VOID;
            }
            static jsVal_t      jsFunction_sleep(JSContext *cx,
                                        JSScriptable *thisObj, int numArgs,
                                        jsVal_t *args, JSFunction *funObj) {
	 	if (numArgs > 0) {
                    JSNativeDebug::sleep(
			(int) JSScriptRuntime::toNumber(cx, args[0]));
		}
		return JS_VAL_VOID;
            }
    } ;

    static JSScriptableObject::jsFunction_t functions[] = {
#define Item(name, length)      { #name,  name, length }
#define ItemAdapter(name, clazz, length)        \
                                { #name,  &clazz::jsFunction_##name, length }
        Item(print, -1),
        Item(printdbg, -1),
        Item(printerr, -1),
        Item(printwarn, -1),
	Item(trace, -1),
	Item(where, -1),
        ItemAdapter(gc, DebugAdapter, 0),
        ItemAdapter(sleep, DebugAdapter, 0),
#undef  ItemAdapter
#undef  Item
    } ;

    ((JSScriptableObject *) scope)->defineFunctionProperties(cx, className,
						TableSize(functions), functions,
                                		JS_PA_DontEnum);
}
void
JSNativeDebug::gc(JSContext *cx)
{
    cx->runtime->gcHeap.gc(cx);
}
#ifdef VX
extern "C" int sysClkRateGet();
#endif
void
JSNativeDebug::sleep(int milliseconds)
{
#ifdef VX
    taskDelay(milliseconds * sysClkRateGet() / 1000);
#else
    struct timespec timespec;

    timespec.tv_sec = milliseconds / 1000;
    timespec.tv_nsec = (milliseconds % 1000) * 1000;
    nanosleep(&timespec, NULL);
#endif
}
#endif /* NATIVE_DEBUG */

