define('jls/io/InputStreamReader', [
  'jls/lang/Class',
  'jls/io/cs/Charset',
  'jls/lang/ByteBuffer',
  'jls/lang/CharBuffer'
], function (
  Class,
  Charset,
  ByteBuffer,
  CharBuffer
) {

var InputStreamReader;
//jls.loader.require('jls.io.BufferedInputStream');
InputStreamReader = Class.create( /** @lends jls.io.InputStreamReader.prototype */
{
    /**
     * Creates a writer.
     * 
     * @param {jls.io.InputStream} input The underlying byte input stream.
     * @param {String} csn The name of the character set to use.
     * @constructs
     * @class A character reader for byte input stream.
     */
    initialize : function(input, csn) {
        /*if (! input.markSupported()) {
            input = new jls.io.BufferedInputStream(input);
        }*/
        this._in = input;
        var charset = csn ? Charset.forName(csn) : Charset.defaultCharset();
        this._decoder = charset.newDecoder();
    	this._bbuffer = ByteBuffer.allocate(1024);
    	this._bbuffer.setLimit(0);
    	this._cbuffer = CharBuffer.allocate(1); // used for the readChar method
    },
    /**
     * Closes this stream.
     *
     */
    close : function() {
        return this._in.close();
    },
    /**
     * Flushs this stream.
     *
     */
    flush : function() {
        return this._in.flush();
    },
    /**
     * Tells if this stream supports the mark and reset methods.
     * 
     * @returns {Boolean} if this stream instance supports the mark and reset methods; false otherwise.
     */
    markSupported : function() {
        return ('mark' in this) && ('reset' in this);
    },
    readChar : function() {
    	var cb = this._cbuffer;
    	cb.clear();
    	cb.setLimit(1);
		this.readCharBuffer(cb);
    	if (cb.remaining() != 0) {
    		return -1;
    	}
    	cb.flip();
    	return cb.getChar();
    },
    /**
     * Reads the underlying stream into a character buffer.
     *
     * @param {jls.lang.CharBuffer} cb The character buffer to read into.
     * @returns {Number} the read byte count.
     */
    readCharBuffer : function(cb) {
        var start = cb.position();
    	// TODO adjust buffer
    	var bb = this._bbuffer;
    	while (cb.remaining() > 0) {
    		if (bb.remaining() == 0) {
        		bb.clear();
            	this._in.read(bb);
            	bb.flip();
            	//jls.logger.warn(bb.remaining() + ' byte(s) read');
    		}
        	//jls.logger.warn('bb.remaining(): ' + bb.remaining());
        	//jls.logger.warn('cb.remaining(): ' + cb.remaining());
    		if (bb.remaining() > 0) {
                this._decoder.decode(bb, cb);
    		}
            if (bb.limit() != bb.capacity()) {
            	break;
            }
    	}
        return cb.position() - start;
    }
});

return InputStreamReader;
});
