package com.lifeonwalden.ebmms.proxy.consumer.intercept;

import com.lifeonwalden.ebmms.client.Client;
import com.lifeonwalden.ebmms.common.bean.Request;
import com.lifeonwalden.ebmms.common.bean.Response;
import com.lifeonwalden.ebmms.common.constant.ReturnCodeEnum;
import com.lifeonwalden.ebmms.liaison.Liaison;
import com.lifeonwalden.ebmms.proxy.consumer.ClientProxy;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Method;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

public class TcpServiceClientInterceptor implements MethodInterceptor, ClientProxy {
    private final static Logger logger = LogManager.getLogger(TcpServiceClientInterceptor.class);

    private Liaison liaison;
    private String serviceName;
    private AtomicInteger counter = new AtomicInteger(0);
    private int maxRetryTimes;
    private int timeoutSeconds;

    public TcpServiceClientInterceptor(String serviceName, int maxRetryTimes, int timeoutSeconds, Liaison liaison) {
        this.liaison = liaison;
        this.serviceName = serviceName;
        this.maxRetryTimes = maxRetryTimes;
        this.timeoutSeconds = timeoutSeconds;
    }

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        Request request = new Request();
        request.setMethod(method.getName()).setService(this.serviceName);
        request.setTimeoutSeconds(this.timeoutSeconds);
        Object[] arguments = invocation.getArguments();
        if (null != arguments && arguments.length > 0) {
            request.setParameters(arguments);
        }

        List<? extends Client> producerList = liaison.fetchProducer(this.serviceName);
        Client client = producerList.get(counter.getAndIncrement() % producerList.size());
        Response response = client.send(request);
        if (ReturnCodeEnum.SUCCESS.getValue() == response.getReturnCode()) {
            return response.getResult();
        } else {
            return null;
        }
    }
}

@@ -1786,24 +1786,107 @@
 %0A        %7D%0A%0A
+        int retryTime = 0;%0A        while (retryTime++ %3C= this.maxRetryTimes) %7B%0A    
         List
@@ -1952,32 +1952,126 @@
 s.serviceName);%0A
+            int currentSize = producerList.size();%0A            if (currentSize %3E 0) %7B%0A        
         Client c
@@ -2127,30 +2127,30 @@
 ) %25 
-producerList.s
+currentS
 ize
-()
 );%0A
+        
     
@@ -2195,16 +2195,24 @@
 quest);%0A
+        
         
@@ -2288,24 +2288,32 @@
             
+        
 return respo
@@ -2341,16 +2341,31 @@
     
-%7D else %7B
+        %7D%0A            %7D
 %0A   
@@ -2373,34 +2373,105 @@
     
+%7D%0A%0A
     
-return null;%0A        %7D
+    throw new RuntimeException(%22Failed to call remote service %22.concat(this.serviceName));
 %0A   

add retry