package org.monkeyscript.lite;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.UnsupportedEncodingException;

import org.mozilla.javascript.*;

public class Global extends ImporterTopLevel {
	
    public Global() {}
    public Global(Context cx) { init(cx); }
	public void init(ContextFactory factory) {
		factory.call(new ContextAction() {
			public Object run(Context cx) {
				init(cx);
				return null;
			}
		});
	}
	
	public void init(Context cx) {
		boolean sealed = cx.isSealed();
		initStandardObjects( cx, sealed );
		defineProperty("global", this, ScriptableObject.DONTENUM | ScriptableObject.READONLY);
		NativeBlob.init( this, sealed );
		//NativeBuffer.init( this, sealed );
		String[] functions = {
			"exec",
			"print",
		};
		defineFunctionProperties(functions, Global.class, ScriptableObject.DONTENUM);
		try {
			defineProperty("__FILE__", this, Global.class.getMethod("js_FILE_", ScriptRuntime.ScriptableObjectClass), null, ScriptableObject.DONTENUM | ScriptableObject.READONLY);
		} catch ( NoSuchMethodException e ) {
			System.out.println(e);
			System.exit(1);
		}
	}
	
	public static Object print(Context cx, Scriptable thisObj, Object[] args, Function funObj) {
        PrintStream out = System.out;
        for (int i=0; i < args.length; i++) {
            if (i > 0)
                out.print(" ");

            // Convert the arbitrary JavaScript value into a string form.
            String s = Context.toString(args[i]);

            out.print(s);
        }
        out.println();
        return Context.getUndefinedValue();
    }
    
	/**
	 * MonkeyScript exec();
	 */
	public static Object exec( Context cx, Scriptable thisObj, Object[] args, Function funObj ) {
		if ( args.length == 0 )
			throw ScriptRuntime.typeError("exec() called without name of script to execute");
		try {
			String scriptFileName = (String) args[0];
			File scriptFile = new File(scriptFileName);
			if ( scriptFile.canRead() ) {
				FileInputStream is = new FileInputStream(scriptFile);
				ScriptReader in = new ScriptReader(is);
				return cx.evaluateReader( thisObj, in, scriptFile.getAbsolutePath(), in.getFirstLine(), null );
			} else {
				throw jsIOError("exec() called with name of a script that doesn't exist or cannot be read");
			}
		} catch( FileNotFoundException e ) {
			throw jsIOError("exec() called with name of a script that doesn't exist");
		} catch( UnsupportedEncodingException e ) {
			throw jsIOError("Unsupported character encodign for exec(): " + e.getMessage());
		} catch( IOException e ) {
			throw jsIOError(e.getMessage());
		}
	}
	
	public static EcmaError jsIOError(String message) {
		return ScriptRuntime.constructError("IOError", message);
	}
	
	public static String js_FILE_(ScriptableObject obj) {
		//This is the correct way to do this, but doesn't work because it's protected and can't be proxied
		//int[] linep = new int[1];
		//String fileName = Context.getSourcePositionFromStackPublic(linep);
		//return fileName;
		return ScriptRuntime.constructError("Error", "").getSourceName();
	}
	
}

@@ -1143,16 +1143,356 @@
 DONLY);%0A
+%09%09%09defineProperty(%22__DIR__%22, this, Global.class.getMethod(%22js_DIR_%22, ScriptRuntime.ScriptableObjectClass), null, ScriptableObject.DONTENUM %7C ScriptableObject.READONLY);%0A%09%09%09defineProperty(%22__LINE__%22, this, Global.class.getMethod(%22js_LINE_%22, ScriptRuntime.ScriptableObjectClass), null, ScriptableObject.DONTENUM %7C ScriptableObject.READONLY);%0A
 %09%09%7D catc
@@ -3529,10 +3529,756 @@
 );%0A%09%7D%0A%09%0A
+%09public static String js_DIR_(ScriptableObject obj) %7B%0A%09%09//This is the correct way to do this, but doesn't work because it's protected and can't be proxied%0A%09%09//int%5B%5D linep = new int%5B1%5D;%0A%09%09//String fileName = Context.getSourcePositionFromStackPublic(linep);%0A%09%09//return (new File(fileName)).getParent();%0A%09%09return (new File(ScriptRuntime.constructError(%22Error%22, %22%22).getSourceName())).getParent();%0A%09%7D%0A%09%0A%09public static int js_LINE_(ScriptableObject obj) %7B%0A%09%09//This is the correct way to do this, but doesn't work because it's protected and can't be proxied%0A%09%09//int%5B%5D linep = new int%5B1%5D;%0A%09%09//String fileName = Context.getSourcePositionFromStackPublic(linep);%0A%09%09//return linep%5B0%5D;%0A%09%09return ScriptRuntime.constructError(%22Error%22, %22%22).getLineNumber();%0A%09%7D%0A%09%0A
 %7D%0A

Support __DIR__ and __LINE__