/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software License
 * version 1.1, a copy of which has been included with this distribution in
 * the LICENSE.txt file.
 */
package org.apache.commons.altrmi.client.impl.stream;

import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.LinkedList;

import org.apache.commons.altrmi.common.AltrmiReply;
import org.apache.commons.altrmi.common.AltrmiRequest;
import org.apache.commons.altrmi.common.SerializationHelper;
import sun.security.krb5.internal.crypto.r;
import sun.tools.tree.SynchronizedStatement;


/**
 * Class CallbackEnabledClientCustomStreamReadWriter
 *
 *
 * @author Vinay Chandrasekharan
 * @version $Revision: 1.0 $
 */
public class CallbackEnabledClientCustomStreamReadWriter 
			extends ClientStreamReadWriter 
			implements Runnable
{
	
    private Object _replyLock = new Object();
    private AltrmiReply _reply =null;
    private LinkedList _requestQueue =  new LinkedList();
	private Thread _messageLoopThread =null;
	private boolean _stopped=false;
	
    private DataInputStream mDataInputStream;
    private DataOutputStream mDataOutputStream;
    private ClassLoader mInterfacesClassLoader;

    /**
     * Constructor ClientCustomStreamReadWriter
     *
     *
     * @param inputStream
     * @param outputStream
     *
     * @throws IOException
     *
     */
    public CallbackEnabledClientCustomStreamReadWriter(InputStream inputStream, OutputStream outputStream, ClassLoader interfacesClassLoader)
            throws IOException {
        mDataOutputStream = new DataOutputStream(new BufferedOutputStream(outputStream));
        mDataInputStream = new DataInputStream(inputStream);

        mInterfacesClassLoader = interfacesClassLoader;
        //thread stores all the messages sent from the server
        _messageLoopThread =  new Thread(this);
        _messageLoopThread.start();
    }

	/*
	 * TODO :--> work somewhere here for callbacks ....
	 * @see Runnable#run()
	 */
	public void run()
	{
		while(!_stopped)
		{
	        try 
	        {
	        	//check if its a REPLY or an REQUEST here ..
	        	//1. check type (request/reply)
	        	//    int type=(int) mDataInputStream.readInt();
	        	//2. if request do ????
	        	//3. else
	        	
				int byteArraySize = (int) mDataInputStream.readInt();
			    byte[] byteArray = new byte[byteArraySize];
			
			    mDataInputStream.read(byteArray);
			
			    //_replyQueue.addFirst(SerializationHelper.getInstanceFromBytes(byteArray, mInterfacesClassLoader));
			    _reply=(AltrmiReply)SerializationHelper.getInstanceFromBytes(byteArray, mInterfacesClassLoader);
			    
			    synchronized(_replyLock)
			    {
			    	_replyLock.notify();
			    }
			} 
			catch(IOException e) 
			{
				_stopped=true;
			} 
			catch(ClassNotFoundException e) 
			{
				e.printStackTrace();				
			}
		
		}
	}
	public AltrmiReply getReplyFromMessageLoop()
	{
		//if(_replyQueue.size()==0)
		if(_reply==null)
		{
			synchronized(_replyLock)
			{
				try 
				{
					_replyLock.wait();
				} 
				catch(InterruptedException e) 
				{
				}
			}
		}
		return _reply;
		//return (AltrmiReply)_replyQueue.removeLast();
	}
    protected synchronized AltrmiReply postRequest(AltrmiRequest altrmiRequest)
            throws IOException, ClassNotFoundException {
        writeRequest(altrmiRequest);
        AltrmiReply r = readReply();
        _reply=null;
        return r;
    }

    private void writeRequest(AltrmiRequest altrmiRequest) throws IOException {

        byte[] aBytes = SerializationHelper.getBytesFromInstance(altrmiRequest);

        mDataOutputStream.writeInt(aBytes.length);
        mDataOutputStream.write(aBytes);
        mDataOutputStream.flush();
    }

    private AltrmiReply readReply() throws IOException, ClassNotFoundException {
		
		return getReplyFromMessageLoop();
    }
    
    
}
