package cn.com.qmth.stmms.common.hessian;

import java.lang.annotation.Annotation;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.remoting.RemoteLookupFailureException;

import com.caucho.hessian.client.HessianProxyFactory;

public abstract class HessianClientRouter<T> {

    @SuppressWarnings("rawtypes")
    public Map<T, Map<Class, Object>> clientMap = new ConcurrentHashMap<T, Map<Class, Object>>();

    private HessianProxyFactory proxyFactory = new HessianProxyFactory();

    @SuppressWarnings("rawtypes")
    public Object getClient(Class serviceInterface, MethodInvocation invocation) {
        // analysisParameter(invocation);
        Object client = getClientMap(getKey()).get(serviceInterface);
        if (client == null) {
            client = refreshClient(serviceInterface);
        }
        return client;
    }

    @SuppressWarnings("rawtypes")
    public Object refreshClient(Class serviceInterface) {
        T key = getKey();
        String[] urls = getUrls(key);
        if (urls != null) {
            for (String url : urls) {
                try {
                    Object proxy = proxyFactory.create(serviceInterface,
                            formatUrl(url) + StringUtils.uncapitalize(serviceInterface.getSimpleName()));
                    getClientMap(key).put(serviceInterface, proxy);
                    return proxy;
                } catch (Exception ex) {
                    throw new RemoteLookupFailureException("Service URL [" + url + serviceInterface.getName()
                            + "] is invalid", ex);
                }
            }
        }
        return null;
    }

    public void clearClient(T key) {
        getClientMap(key).clear();
    }

    public abstract String[] getUrls(T key);

    @SuppressWarnings("unchecked")
    private T getKey() {
        try {
            return (T) HessianClientContext.getKey();
        } catch (Exception e) {
            throw new IllegalClientKeyException("当前远程服务调用者没有设置正确的client key");
        }
    }

    @SuppressWarnings("rawtypes")
    private Map<Class, Object> getClientMap(T key) {
        Map<Class, Object> map = clientMap.get(key);
        if (map == null) {
            map = new ConcurrentHashMap<Class, Object>();
            clientMap.put(key, map);
        }
        return map;
    }

    /**
     * 分析调用方法中的参数，如果出现@HessianClientKey标注的参数，则自动置入上下文，作为client key使用
     * 
     * @param invocation
     */
    @SuppressWarnings("unused")
    private void analysisParameter(MethodInvocation invocation) {
        Annotation[][] annotations = invocation.getMethod().getParameterAnnotations();
        if (annotations != null && annotations.length > 0 && annotations.length == invocation.getArguments().length) {
            for (int i = 0; i < annotations.length; i++) {
                boolean flag = false;
                if (annotations[i] != null && annotations[i].length > 0) {
                    for (Annotation annotation : annotations[i]) {
                        if (annotation instanceof HessianClientKey) {
                            flag = true;
                            break;
                        }
                    }
                }
                if (flag) {
                    HessianClientContext.setKey(invocation.getArguments()[i]);
                    break;
                }
            }
        }
    }

    private String formatUrl(String url) {
        if (url.endsWith("/")) {
            return url;
        } else {
            return url + "/";
        }
    }
}
