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

package com.xruby.runtime.value;

import java.io.*;
import com.xruby.runtime.lang.*;

public class RubyIO extends RubyBasic {
	private RandomAccessFile file_ = null;

	RubyIO(String filename, String mode) {
		super(RubyRuntime.FileClass);//FIXME create a new class for file
		open(filename, mode);
	}
	
	private String translateMode(String mode) {
		//TODO mode of RandomAccessFile is not as same as fopen()
		if (mode.equals("w")) {
			return "rw";
		} else if (mode.equals("rb")) {
			return "r";
		} else {
			return mode;
		}
	}
	
	private boolean open(String filename, String mode) {
		assert(null == file_);
		try {
			file_ = new RandomAccessFile(filename, translateMode(mode));
			if (mode.equals("w")) {
				file_.setLength(0);
			}
			return true;
		} catch (FileNotFoundException e) {
			return false;
		} catch (IOException e) {
			file_ = null;
			return false;
		}
	}
	
	public boolean eof() {
		try {
			return file_.length() == file_.getFilePointer();
		} catch (IOException e) {
			throw new RubyException(RubyRuntime.IOErrorClass, e.toString());
		}
	}
	
	public void close() {
		if (null != file_) {
			try {
				file_.close();
				file_ = null;
			} catch (IOException e) {
				//Do not care
			}
		}
	}
	
	public boolean print(String s) {
		if (null == file_) {
			throw new RubyException(RubyRuntime.IOErrorClass, "file is not opened");
		}
		
		try {
			file_.writeBytes(s);
			return true;
		} catch (IOException e) {
			return false;
		}
	}

	private RubyValue readsTheEntireContents() throws IOException {
		int size = (int)file_.length();//TODO converted long to int
		byte[] buffer = new byte[size];
		file_.read(buffer);
		return ObjectFactory.createString(new String(buffer));
	}

	private RubyValue readUntilSeperator(String separator) throws IOException {
		//FIXME This is cheating, should read until separator
		String s = file_.readLine();
		if (null == s) {
			return ObjectFactory.nilValue;
		} else {
			return ObjectFactory.createString(s + "\n");
		}
	}
	
	public RubyValue gets(RubyValue separator) {
		if (null == file_) {
			throw new RubyException(RubyRuntime.IOErrorClass, "file is not opened");
		}

		try {
			if (ObjectFactory.nilValue == separator) {
				return readsTheEntireContents();
			}

			if (!(separator instanceof RubyString)) {
				throw new RubyException(RubyRuntime.TypeErrorClass, "can't convert " + separator.getRubyClass().getName() + " into String");
			}

			RubyString s = (RubyString)separator;
			
			return readUntilSeperator(s.toString());
		} catch (IOException e) {
			throw new RubyException(RubyRuntime.IOErrorClass, e.toString());
		}
	}
	
	public RubyValue read() {
		if (null == file_) {
			throw new RubyException(RubyRuntime.IOErrorClass, "file is not opened");
		}
		
		try{
			return readsTheEntireContents();
		} catch (IOException e) {
			throw new RubyException(RubyRuntime.IOErrorClass, e.toString());
		}
	}
	
	public RubyValue read(long length) {
		if (null == file_) {
			throw new RubyException(RubyRuntime.IOErrorClass, "file is not opened");
		}
		
		try{
			long size = file_.length();
			size = Math.min(length, size);
			byte[] buffer = new byte[(int)size];
			file_.read(buffer);
			return ObjectFactory.createString(new String(buffer));
		} catch (IOException e) {
			throw new RubyException(RubyRuntime.IOErrorClass, e.toString());
		}
	}
	
	public RubyValue read(int length, int offset) {
		if (null == file_) {
			throw new RubyException(RubyRuntime.IOErrorClass, "file is not opened");
		}
		
		try{
			file_.seek(offset);
		} catch (IOException e) {
			throw new RubyException(RubyRuntime.IOErrorClass, e.toString());
		}
		
		return read(length);
	}
}

@@ -1813,16 +1813,20 @@
 ze%5D;%0D%0A%09%09
+if (
 file_.re
@@ -1835,19 +1835,81 @@
 (buffer)
-;%0D%0A
+ %3C 0) %7B%0D%0A%09%09%09return ObjectFactory.createString(%22%22);%0D%0A%09%09%7D else %7B%0D%0A%09
 %09%09return
@@ -1954,24 +1954,29 @@
 (buffer));%0D%0A
+%09%09%7D%0D%0A
 %09%7D%0D%0A%0D%0A%09priva
@@ -3464,24 +3464,28 @@
 )size%5D;%0D%0A%09%09%09
+if (
 file_.read(b
@@ -3490,19 +3490,75 @@
 (buffer)
-;%0D%0A
+ %3C 0) %7B%0D%0A%09%09%09%09return ObjectFactory.nilValue;%0D%0A%09%09%09%7D else %7B%0D%0A%09
 %09%09%09retur
@@ -3604,24 +3604,30 @@
 (buffer));%0D%0A
+%09%09%09%7D%0D%0A
 %09%09%7D catch (I

fix IO#read: return "" or nil at the end of the file