package hh.dejsem.net;

import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;

import hh.dejsem.K;
import hh.lib.D;

public class NetScIO implements NetIO, GetPut {
	/**----------------------------------------------------------
	 * nonSSL blocking network IO
	 * ----------------------------------------------------------*/
	D d;
	ServerSocket ssc;
	Socket sc = null;
	InputStream in = null;
	public OutputStream out = null;
	ReadableByteChannel ic;
	WritableByteChannel oc;
	/* ----------------------------------------------------------*/

	public NetScIO(D d) { this.d = d.klon(this); }

	public void bind(String host, int port) throws Exception {}

	public boolean isBound() { return ssc.isBound(); }

	public void accept() throws Exception {}

	public void connect(InetSocketAddress hostIp) throws Exception {
		sc = new Socket();
		sc.connect(hostIp, K.socketTO);		// oddělit connect TO a read TO
		sc.setSoTimeout(K.socketTO);
		in = sc.getInputStream();
		ic = Channels.newChannel(in);
		out = sc.getOutputStream();
		oc = Channels.newChannel(out);
	}

	public boolean get(ByteBuffer buf) throws Exception {		// false on EOD
		if(d.ll(5)) d.l("get from net, buf=" + D.bufStat(buf) + " ...");
		try { while(buf.hasRemaining()) {
				int n;
				n = ic.read(buf);
				if(d.ll(5)) d.l(String.format("%d bytes partially read", n));
				if(n < 0) break;
			}
		}
		catch(Exception x) {
			closeSc();
			throw new Exception("net channel read", x); };
		if(d.ll(5)) d.l("" + buf.position()+ " read");
		return buf.position() > 0;
	}

	public int put(ByteBuffer buf) throws Exception {
		int n = 0;
		if(d.ll(5)) d.l("output to net, buf=" + D.bufStat(buf) + " ...");
		while(buf.hasRemaining()) {
			n = 0;
			try { n = oc.write(buf); }
			catch(Exception x) {
				closeSc();
				throw new Exception("net channel write", x); }
			if(d.ll(5)) d.l("" + n + " written"); }
		buf.clear();
		return n;
	}

	public void closeSc() throws Exception { if(sc != null) sc.close(); }

	public void closeSsc() throws Exception {
		if(ssc != null) {
			ssc.close();
			ssc = null; }
	}
}
