package ethereumjava.solidity;

import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import ethereumjava.exception.EthereumJavaException;
import ethereumjava.module.Eth;

/**
 * Created by gunicolas on 30/08/16.
 */
public class Contract<T extends ContractType> {

    Class<T> abi;
    String address;
    Eth eth;

    public Contract(Eth eth){
        this.eth = eth;
    }

    public Contract<T> withAbi(Class<T> abi){
        this.abi = abi;
        return this;
    }

    public T at(String address){
        this.address = address;
        return (T) Proxy.newProxyInstance(abi.getClassLoader(),new Class[]{abi},new InvocationHandler());
    }

    class InvocationHandler implements java.lang.reflect.InvocationHandler{

        @Override
        public SolidityElement invoke(Object proxy, Method method, Object[] args) throws Throwable {

            if( method.getReturnType().isAssignableFrom(SolidityFunction.class) ){
                return new SolidityFunction(address,method,eth,args);
            } else if( method.getReturnType().isAssignableFrom(SolidityEvent.class) ){
                return new SolidityEvent(address,method,eth);
            }
            throw new EthereumJavaException("Contract element return type is invalid");
        }
    }

}

@@ -247,53 +247,11 @@
 ract
-%3CT extends ContractType%3E %7B%0A%0A    Class%3CT%3E abi;
+ %7B%0A
 %0A   
@@ -296,58 +296,92 @@
 lic 
-Contract(Eth eth)%7B%0A        this.eth = eth;
+final class ContractInstance%3CT extends ContractType%3E %7B%0A        Class%3CT%3E clazz;%0A
 %0A    
-%7D%0A%0A
     
@@ -399,19 +399,16 @@
 ract
-%3CT%3E withAbi
+Instance
 (Cla
@@ -418,11 +418,15 @@
 T%3E a
-bi)
+Clazz) 
 %7B%0A  
@@ -435,52 +435,43 @@
     
-this.abi = abi;%0A        return this;
+    clazz = aClazz;%0A        %7D%0A
 %0A    
-%7D%0A%0A
     
@@ -507,16 +507,29 @@
         
+  
+  Contract.
 this.add
@@ -548,24 +548,28 @@
 ss;%0A        
+  
+  
 return (T) P
@@ -590,19 +590,21 @@
 nstance(
-abi
+clazz
 .getClas
@@ -629,11 +629,13 @@
 s%5B%5D%7B
-abi
+clazz
 %7D,ne
@@ -658,16 +658,220 @@
 ler());%0A
+        %7D%0A%0A    %7D%0A%0A    public Contract(Eth eth)%7B%0A        this.eth = eth;%0A    %7D%0A%0A    public %3CT extends ContractType%3E ContractInstance%3CT%3E withAbi(Class%3CT%3E clazz)%7B%0A        return new ContractInstance(clazz);%0A
     %7D%0A%0A 

Allow to not cast ethereum Java contract