package Default;

import java.math.BigInteger;

import org.web3j.crypto.Credentials;
import org.web3j.crypto.WalletUtils;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.ManagedTransaction;
import org.web3j.tx.gas.ContractGasProvider;
import org.web3j.tx.gas.StaticGasProvider;

public class EthereumSolidityFilterApplication {

	public static void main(String[] args) {

		/*
		 * Open a connection to the geth node using rpc
		 */
		Web3j web3 = Web3j.build(new HttpService("http://localhost:8545"));
		
		try {
			/*
			 * Use RPC send() to get the client version of geth
			 */
			Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send();
			String clientVersion = web3ClientVersion.getWeb3ClientVersion();
			System.out.println("Client is version: "+clientVersion);
			
			/*
			 * Open a keystore file using the provided password 
			 * to load transaction signing credentials
			 */
			System.out.println("Getting credentials");
	        Credentials credentials = WalletUtils.loadCredentials("password", "/home/ubuntu/.ethereum/keystore/UTC--2019-04-27T14-21-30.839550149Z--a1ffbe52c67aa5a9b45a15af63501a9e690c06ad");

	        /*
	         * We use the wrapper class to deploy the smart 
	         * contract, using a synchronous call 
	         * to wait until it is mined and available
	         */
			System.out.println("Deploying contract");
			ContractGasProvider gasPrv = new StaticGasProvider(ManagedTransaction.GAS_PRICE, new BigInteger("4000000"));
			
	        Contract2 contract = Contract2.deploy(web3, credentials, gasPrv).send();
	        
	        /*
	         * The return value will have the contract address
	         * (as well as the transaction receipt for more info)
	         */
	        System.out.println("Smart contract address: " + contract.getContractAddress());

	        System.out.println("\nTransaction Info");
	        System.out.println("  Tx Hash: " + contract.getTransactionReceipt().get().getTransactionHash());
	        System.out.println("  Block Hash: " + contract.getTransactionReceipt().get().getBlockHash());
	        System.out.println("  Block Number: " + contract.getTransactionReceipt().get().getBlockNumber());
	        System.out.println("  Tx Index: " + contract.getTransactionReceipt().get().getTransactionIndex());
	        System.out.println("  Status: " + contract.getTransactionReceipt().get().getStatus());
	        System.out.println("  Gas Used: " + contract.getTransactionReceipt().get().getGasUsed());

	        /*
	         * Let's check that it's valid
	         */
	        if (contract.isValid()) {
	        	System.out.println("Contract is valid!");
		        /*
		         * We can now use the wrapper class to interact with the contract
		         * 
		         * Again, we use synchronous calls to wait until the change is 
		         * mined into the blockchain before we continue
		         */
		        System.out.println("Messages length: " + contract.getLength().send());
		        System.out.println("Storing new message");
		        TransactionReceipt rcpt = contract.storeMessage("Hello World").send();
		        
		        /*
		         * We can query the events raised by this method invocation
		         */
		        for (Contract2.ReceiveMessageEventResponse event : contract.getReceiveMessageEvents(rcpt)) {
		        	System.out.println(event.getClass().getName());
		        	System.out.println("Message sender: " + event.messageSender);
		        	System.out.println("Message: " + event.message);
		        	System.out.println("Message number: " + event.messageNumber);
		        }

		        /* 
		         * Let's make sure everything worked by getting the counter value and
		         * the message at that counter
		         */
		        BigInteger length = contract.getLength().send();
		        System.out.println("Messages length: " + length);
		        System.out.println("Last message: " + contract.getMessageAt(length.subtract(new BigInteger("1"))).send());

		        System.out.println("Done.");
	        } else {
	        	System.out.println("Contract is NOT valid; something went wrong; Oops.");
	        }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
		/*
		 * Close the RPC connection when we're done
		 */
		web3.shutdown();
	}

}
