package BFTSmartBlockchain;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;

import bftsmart.tom.ServiceProxy;

public class BlockchainClient {
	
	ServiceProxy serviceProxy;
	
	public BlockchainClient(int clientId) {
		serviceProxy = new ServiceProxy(clientId);
	}
	
	public BlockchainReplyType addTransaction(Transaction tx) {
		try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
				ObjectOutput objOut = new ObjectOutputStream(byteOut);) {
			
			objOut.writeObject(BlockchainRequestType.ADD_TRANSACTION);
			objOut.writeObject(tx);
			objOut.flush();
			byteOut.flush();
			
			byte[] reply = serviceProxy.invokeOrdered(byteOut.toByteArray());
			if (reply.length == 0)
				return null;
			try (ByteArrayInputStream byteIn = new ByteArrayInputStream(reply);
					ObjectInput objIn = new ObjectInputStream(byteIn)) {
				BlockchainReplyType r = (BlockchainReplyType) objIn.readObject();
				return r;
			}
				
		} catch (IOException | ClassNotFoundException e) {
			System.out.println("Exception adding transaction: " + e);
		}
		return null;
	}
	
	public Block getHead() {
		try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
				ObjectOutput objOut = new ObjectOutputStream(byteOut);) {
			
			objOut.writeObject(BlockchainRequestType.GET_HEAD);
			objOut.flush();
			byteOut.flush();
			
			byte[] reply = serviceProxy.invokeUnordered(byteOut.toByteArray());
			if (reply.length == 0)
				return null;
			try (ByteArrayInputStream byteIn = new ByteArrayInputStream(reply);
					ObjectInput objIn = new ObjectInputStream(byteIn)) {
				Block b = (Block) objIn.readObject();
				System.out.println("Head is: " + b);
				return b;
			}
				
		} catch (IOException | ClassNotFoundException e) {
			System.out.println("Exception getting head: " + e);
		}
		return null;
	}
	
	public Block getBlock(byte[] blockHash) {
		try (ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
				ObjectOutput objOut = new ObjectOutputStream(byteOut);) {
			
			objOut.writeObject(BlockchainRequestType.GET_BLOCK);
			objOut.writeObject(blockHash);
			objOut.flush();
			byteOut.flush();
			
			byte[] reply = serviceProxy.invokeOrdered(byteOut.toByteArray());
			if (reply.length == 0)
				return null;
			try (ByteArrayInputStream byteIn = new ByteArrayInputStream(reply);
					ObjectInput objIn = new ObjectInputStream(byteIn)) {
				Block b = (Block) objIn.readObject();
				System.out.println("Received block: " + b);
				return b;
			}
				
		} catch (IOException | ClassNotFoundException e) {
			System.out.println("Exception getting block: " + e);
		}
		return null;
	}
}