/** 
 * Copyright 2005-2007 Xue Yong Zhi, Jie Li, Ye Zheng
 * Distributed under the GNU General Public License 2.0
 */

package com.xruby.runtime.builtin;

import com.xruby.runtime.lang.*;
import com.xruby.runtime.value.*;

class IO_write extends RubyOneArgMethod {
	protected RubyValue run(RubyValue receiver, RubyValue arg, RubyBlock block) {
		RubyString value;
		if (arg instanceof RubyString) {
			value = (RubyString)arg;
		} else {
			RubyValue str = RubyAPI.callPublicMethod(arg, null, null, "to_s");
			value = (RubyString) str;
		}
		
		if (receiver instanceof RubyIO) {
			((RubyIO)receiver).print(value.toString());
		} else {
			System.out.print(value.toString());//TODO this is a hack, better create a new class to represent STDOUT
		}
		return ObjectFactory.createFixnum(value.length());
	}
}

class IO_print extends Kernel_print {
	protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block) {
		return _run(receiver, args, block);
	}
}

class IO_close extends RubyNoArgMethod {
	protected RubyValue run(RubyValue receiver, RubyBlock block) {
		if (receiver instanceof RubyIO) {
			//not stdout, stderr, stdin
			((RubyIO)receiver).close();
		}
		return ObjectFactory.nilValue;
	}
}

class IO_gets extends RubyVarArgMethod {
	protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block) {
		if (receiver instanceof RubyIO) {
			RubyValue seperator = (null == args) ?  GlobalVariables.get("$/") : args.get(0);
			GlobalVariables.set(((RubyIO)receiver).gets(seperator), "$_");
		} else {
			//TODO stdout, stderr, stdin
			GlobalVariables.set(ObjectFactory.nilValue, "$_");
		}

		return GlobalVariables.get("$_");
	}
}

class IO_eof extends RubyNoArgMethod {
	protected RubyValue run(RubyValue receiver, RubyBlock block) {
		RubyIO io = (RubyIO)receiver;
		if (io.eof()) {
			return ObjectFactory.trueValue;
		} else {
			return ObjectFactory.falseValue;
		}
	}
}

class IO_read extends RubyMethod {
	public IO_read() {
		super(3, false, 2);
	}

	protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block) {
		RubyString fileName = (RubyString)args.get(0);
		RubyIO io = ObjectFactory.createFile(fileName.toString(), "r");
		int offset;
		int length;
		if (args.size() == 1){
			return io.read();
		}else{
			length = ((RubyFixnum)args.get(1)).intValue();
			if(args.size() == 2){			
				return io.read(length);
			}else{
				offset = ((RubyFixnum)args.get(2)).intValue();
				return io.read(length, offset);
			}
		}
	}
}

public class IOClassBuilder {
	public static void initialize() {
		RubyClass c = RubyRuntime.IOClass;
		c.defineMethod("write", new IO_write());
		c.defineMethod("print", new IO_print());
		c.defineMethod("gets", new IO_gets());
		c.defineMethod("close", new IO_close());
		RubyMethod eof = new IO_eof();
		c.defineMethod("eof", eof);
		c.defineMethod("eof?", eof);
		
		c.getSingletonClass().defineMethod("read", new IO_read());
		
	}
}

@@ -1994,24 +1994,319 @@
 ead extends 
+RubyVarArgMethod %7B%0D%0A%09protected RubyValue run(RubyValue receiver, RubyArray args, RubyBlock block) %7B%0D%0A%09%09RubyIO io = (RubyIO)receiver;%0D%0A%09%09if (null == args) %7B%0D%0A%09%09%09return io.read();%0D%0A%09%09%7D else %7B%0D%0A%09%09%09return io.read(((RubyFixnum)args.get(0)).intValue());%0D%0A%09%09%7D%0D%0A%09%7D%0D%0A%7D%0D%0A%0D%0Aclass IO_read_singleton extends 
 RubyMethod %7B
@@ -2322,16 +2322,26 @@
  IO_read
+_singleton
 () %7B%0D%0A%09%09
@@ -2618,16 +2618,17 @@
 () == 1)
+ 
 %7B%0D%0A%09%09%09re
@@ -2647,20 +2647,22 @@
 ();%0D%0A%09%09%7D
+ 
 else
+ 
 %7B%0D%0A%09%09%09le
@@ -2712,16 +2712,17 @@
 ;%0D%0A%09%09%09if
+ 
 (args.si
@@ -2731,16 +2731,17 @@
 () == 2)
+ 
 %7B%09%09%09%0D%0A%09%09
@@ -2771,20 +2771,22 @@
 );%0D%0A%09%09%09%7D
+ 
 else
+ 
 %7B%0D%0A%09%09%09%09o
@@ -3261,24 +3261,66 @@
 f?%22, eof);%0D%0A
+%09%09c.defineMethod(%22read%22, new IO_read());%0D%0A
 %09%09%0D%0A%09%09c.getS
@@ -3359,32 +3359,42 @@
 ad%22, new IO_read
+_singleton
 ());%0D%0A%09%09%0D%0A%09%7D%0D%0A%7D%0D

add IO#read