package jade.imtp.leap.nio;

//#J2ME_EXCLUDE_FILE
import jade.imtp.leap.JICP.JICPPacket;
import jade.imtp.leap.JICP.JICPProtocol;
import jade.imtp.leap.http.HTTPHelper;
import jade.imtp.leap.http.HTTPRequest;
import jade.imtp.leap.http.HTTPResponse;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author Eduard Drenth: Logica, 22-sep-2009
 * 
 */
public class NIOHTTPHelper extends HTTPHelper implements BufferTransformer {

	//private boolean needToRead = false;
	NIOJICPConnection connection;
	private static Logger log = Logger.getLogger(NIOHTTPHelper.class.getName());


	public static ByteBuffer readByteBufferFromHttp(InputStream is) throws IOException {
		HTTPRequest request = new HTTPRequest();
		request.readFrom(is);
		if (is.markSupported()) {
			is.mark(2);
			if (is.read() != -1) {
				is.reset();
				throw new IOException("bytes left in stream after constructing HTTPRequest");
			}
		}
		if (request.getMethod().equals("GET")) {
			String recipientID = request.getField(RECIPIENT_ID_FIELD);
			JICPPacket pkt = new JICPPacket(JICPProtocol.CONNECT_MEDIATOR_TYPE, JICPProtocol.DEFAULT_INFO, recipientID, null);
			ByteBuffer b = ByteBuffer.allocateDirect(pkt.getLength());
			MyOut out = new MyOut(b);
			pkt.writeTo(out);
			b.flip();
			return b;
		} else {
			// Read the JICPPacket from the HTTP request payload
			byte[] a = request.getPayload();
			ByteBuffer b = ByteBuffer.allocateDirect(a.length);
			MyOut out = new MyOut(b);
			out.write(a, 0, a.length);
			b.flip();
			return b;
		}
	}
	public NIOHTTPHelper(NIOJICPConnection connection) {
		this.connection = connection;
	}

	private static ByteBuffer wrapInHttpResponse(ByteBuffer pkt) throws IOException {
		byte[] b = new byte[pkt.remaining()];
		pkt.get(b, 0, pkt.remaining());
		HTTPResponse response = wrapInHttp(b);
		ByteArrayOutputStream out = new ByteArrayOutputStream();
		response.writeTo(out);
		return ByteBuffer.wrap(out.toByteArray());
	}

	private static ByteBuffer constructJICPPacket(ByteBuffer input) throws IOException {
		byte[] out = new byte[input.remaining()];
		input.get(out, 0, input.remaining());
		if (log.isLoggable(Level.FINE)) {
			log.fine("trying to read jicp packet from http: \n" + new String(out));
		}
		return readByteBufferFromHttp(new ByteArrayInputStream(out));
	}

	public synchronized ByteBuffer postprocessBufferRead(ByteBuffer data) throws IOException {
		//needToRead = false;
		data.mark();
		try {
			return constructJICPPacket(data);
		} catch (EOFException ex) {
			if (log.isLoggable(Level.FINE)) {
				log.log(Level.FINE, "not enough data available, wait for more", ex);
			}
			//needToRead = true;
			// incomplete, wait for more data
			data.reset();
		}
		return NIOHelper.EMPTY_BUFFER;
	}

	public synchronized ByteBuffer preprocessBufferToWrite(ByteBuffer dataToSend) throws IOException {
		return wrapInHttpResponse(dataToSend);
	}

	public boolean needSocketData() {
		//return needToRead;
		return false;
	}

	private static class MyOut extends ByteArrayOutputStream {

		private ByteBuffer buffer;

		public MyOut(ByteBuffer b) {
			this.buffer = b;
		}

		@Override
		public synchronized void write(int b) {
			buffer.put((byte) b);
		}

		@Override
		public synchronized void write(byte[] b, int off, int len) {
			buffer.put(b, off, len);
		}
	}
}
