#include <stdio.h>
#include <jsapi.h>
#include <sys/types.h>
#include <sys/stat.h>

/* Function Prototypes */
JSBool js_engine_execute_file(JSContext *ctx, const char *file);

JSClass js_global_object_class = {
  "System",
  0,
  JS_PropertyStub,
  JS_PropertyStub,
  JS_PropertyStub,
  JS_PropertyStub,
  JS_EnumerateStub,
  JS_ResolveStub,
  JS_ConvertStub,
  JS_FinalizeStub,
  JSCLASS_NO_OPTIONAL_MEMBERS
};

int main(int argc, char **argv){
    char *fileToRun=NULL;
    JSRuntime *rt=NULL;
    JSContext *cx=NULL;
    JSObject *obj=NULL;

    if (argc > 1){
        fileToRun = argv[1];
    }
    
    rt = JS_NewRuntime(8L*1024L);
    if (!rt){
        printf("Failed to initialize JS Runtime.\n");
        return 1;
    }

    cx = JS_NewContext(rt, 8L*1024L*1024L);
    if (!cx){
        printf("Failed to initialize JS Context.\n");
        JS_DestroyRuntime(rt);
        return 1;
    }

    obj = JS_NewObject(cx, &js_global_object_class, NULL, NULL);
    if (!obj){
        printf("Failed to create global object.\n");
        JS_DestroyContext(cx);
        JS_DestroyRuntime(rt);
        return 1;
    }

    JS_InitStandardClasses(cx, obj);
    
    if (fileToRun){
        if (js_engine_execute_file(cx, fileToRun)){
          printf("File %s has been successfully executed.\n", fileToRun);
        }
        else {
          printf("Failed to executed %s for an unknown reason.\n", fileToRun);
        }
    }
    else {
        printf("Usage: %s file\n", argv[0]);
    }


    JS_DestroyContext(cx);
    JS_DestroyRuntime(rt);
    return 0;
}


JSBool js_engine_execute_file(JSContext *ctx, const char *file){
    JSScript *script;
    jsval returnValue;
    JSObject *global = JS_GetGlobalObject(ctx);
    struct stat statinfo;

    if (file == NULL){
        return JS_FALSE;
    }

    if (stat(file, &statinfo) == -1){
        return JS_FALSE;
    }

    if (!S_ISREG(statinfo.st_mode)){
        return JS_FALSE;
    }

    script = JS_CompileFile(ctx, global, file);

    if (script == NULL){
        return JS_FALSE;
    }

    return JS_ExecuteScript(ctx, global, script, &returnValue);
}

