package com.platform.plugs.live.proxy;


import com.platform.plugs.common.rpc.ErrorCode;
import com.platform.plugs.common.rpc.ResponseResult;
import com.platform.plugs.common.rpc.RpcResponse;
import com.platform.plugs.live.annotation.RpcParam;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.lang.reflect.Proxy;
import java.util.Collection;

/**
 * @Author TONG
 * @Date 2019/3/6 14:37
 **/
public class HandlerProxy<T> implements InvocationHandler {

    private final Log log = LogFactory.getLog(this.getClass());

    private T handler;

    private RpcResponse PARAMS_ERROR_RESPONSE = new RpcResponse(RpcResponse.ERROR_STATUS, ResponseResult.ERROR, ErrorCode.ParamsError.toString(), "params error");

    public T getHandler(T handler) {
        this.handler = handler;
        Class<?> clazz = handler.getClass();
        return (T)Proxy.newProxyInstance(clazz.getClassLoader(), clazz.getInterfaces(), this);
    }

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

        Parameter[] params = method.getParameters();
        for(int index=0; index<params.length;index++) {
            Parameter param = params[index];
            if(param.isAnnotationPresent(RpcParam.class)) {
                RpcParam annotation = param.getAnnotation(RpcParam.class);
                if(annotation.required() && isArgNull(args[index])) {
                    log.error(handler.getClass() + "." + method.getName() + " error, param [" + index +"] is null" );
                    if(method.getReturnType() == RpcResponse.class)
                        return PARAMS_ERROR_RESPONSE;
                    else
                        return null;
                }
            }
        }

        Object result = method.invoke(this.handler, args);
        return result;
    }

    private boolean isArgNull(Object value) {

        if(value == null) return true;

        if(value instanceof String) {
            return value.toString().trim().length() <= 0;
        } else if(value instanceof Object[]) {
            return ((Object[]) value).length <= 0;
        } else if(value instanceof Collection) {
            return ((Collection)value).size() <= 0;
        }
        return false;
    }
}
