/************************************************************************
*
* Copyright (c) 2003-2004, C&C Research Laboratories, NEC Europe Ltd.
*
* Copyright in this library belongs to C&C Research Laboratories,
* Rathausallee 10, 53757 Sankt Augustin, Germany.
*
* This software may not be used, sold, licensed, transferred, copied
* or reproduced in whole or in part in any manner or form or in or
* on any media by any person other than in accordance with the terms
* of the Licence Agreement supplied with the software, or otherwise
* without the prior written consent of the copyright owners.
*
* This software is distributed WITHOUT ANY WARRANTY, without even the
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE, except where stated in the Licence Agreement supplied with
* the software.
*
*  Created By :           Federico Crazzolara
*  Created for Project :  GEMSS (IST-2001-37153)
*
************************************************************************/

package de.nece.ccrl.util;


import java.io.*;




public class OutputInputStream extends InputStream {    

    private static final int BUF_SIZE = 1024;

    private byte[] b = new byte[BUF_SIZE];
    private int pos = 0;
    private int av = 0;
    private boolean end = false;
    

    public synchronized void close() throws IOException {
	end = true;
	try{
	    this.notifyAll();
	} catch(Exception e) {e.printStackTrace();}
    }

    public int available() throws IOException {
	return av;
    }

    public synchronized void write(byte[] buf, int length) throws IOException {
	

	if (length>BUF_SIZE) throw new IOException("Buffer size is too small for this write operation");

	while (((BUF_SIZE-av)<length) && (!end)) 
	    try{
		this.wait();
	    } catch(Exception e) {e.printStackTrace();}
	if (end) try{
	    this.notifyAll();
	} catch(Exception e) {e.printStackTrace();}
	else {
	    for (int i=0;i<length;i=i+1) {
		int fin = (pos + av + i) % BUF_SIZE;
		b[fin] = buf[i];					
	    }
	    
	    av = av + length;

	    
	    try{
		this.notifyAll();
	    } catch(Exception e) {e.printStackTrace();}	    

	   
	}
	
    }


    public synchronized int read() throws IOException {	
	
	byte[] temp = new byte[1];
	if (this.read(temp)<0) return -1;
	else {
	    
	    if (temp[0]<0) return (256+temp[0]);
	    else return temp[0];	
	}
    }

   
    public synchronized int read(byte[] a) throws IOException {
	
	if (a.length == 0) {
	    
	    return 0;
	}
	while ((av==0) && (!end)) 
	    try{
		this.wait();
	    } catch(Exception e) {e.printStackTrace();}

	if ((av==0) && (end)) {
	    try{
		this.notifyAll();
	    } catch(Exception e) {e.printStackTrace();}
	    
	    return -1;
	}
	
	int num = Math.min(a.length,av);

	for(int i=0;i<num;i=i+1){	    
	    a[i] = b[pos];	
	    pos = (pos + 1) % BUF_SIZE;   
	}

	av = av - num;

	
	try{
		this.notifyAll();
	} catch(Exception e) {e.printStackTrace();}
	
	return num;
    }

   

}




