package com.twjitm.core.common.service.rpc.client.proxy;

import com.twjitm.core.common.factory.NettyRpcRequestFactory;
import com.twjitm.core.common.netstack.entity.rpc.NettyRpcRequestMessage;
import com.twjitm.core.common.service.rpc.client.AbstractNettyRpcConnectManager;
import com.twjitm.core.common.service.rpc.client.NettyRpcFuture;
import com.twjitm.core.common.service.rpc.client.NettyRpcContextHolder;
import com.twjitm.core.common.service.rpc.client.NettyRpcContextHolderObject;
import com.twjitm.core.common.service.rpc.network.NettyRpcClient;
import com.twjitm.core.common.service.rpc.service.NettyRpcClientConnectService;
import com.twjitm.core.common.service.rpc.service.NettyRpcProxyService;
import com.twjitm.core.spring.SpringServiceManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * 异步rpc代理，一个目标异步代理对象，创建过程由{@link NettyRpcProxyService#createProxy(Class)}
 * {@link NettyAsyncRpcProxy}代理类主要实现的功能：
 * 将所需要的代理方法名称和具体参数通过{@link NettyRpcClient} 传递给远程目标代理服务器。本地方法会立即返回一个
 * 空{@link NettyRpcFuture} 对象，通过注入回调函数的方式，监听{@link NettyRpcFuture} 的状态变化，
 * 最后通过注入监听回调函数的方式来实现异步rcp远程服务调用
 * </p>
 * <p>
 *
 * @author twjitm - [Created on 2018-08-20 14:46]
 * @company https://github.com/twjitm/
 * @jdk java version "1.8.0_77"
 */
public class NettyAsyncRpcProxy<T> implements INettyAsyncRpcProxy {
    private Logger logger=LoggerFactory.getLogger(NettyAsyncRpcProxy.class);
    /**
     * <p>
     * 代理接口类信息：此处的类信息必须是接口的，而不是实现类的。
     * 应为代理模式采用的动态代理，动态代理也成为接口代理，具体查看
     *
     * @see <a href="https://my.oschina.net/u/3296367/blog/1475258 "><h2>动态代理模式详解</h2></a>
     * </p>
     */
    private Class<T> clazz;

    public NettyAsyncRpcProxy(Class<T> clazz) {
        this.clazz = clazz;
    }

    @Override
    public NettyRpcFuture call(String funcName, Object... args) {
        //获得一个持有对象
        NettyRpcContextHolderObject rpcContextHolderObject = NettyRpcContextHolder.getContext();

        //联合器服务类
        NettyRpcClientConnectService rpcClientConnectService =
                SpringServiceManager.getSpringLoadService().getNettyRpcClientConnectService();

        //更具类型获取一个rpc联合管理器
        AbstractNettyRpcConnectManager abstractRpcConnectManager
                = rpcClientConnectService.getNettyRpcConnectManager(
                rpcContextHolderObject.getNettyGameTypeEnum());
        //根据服务id，获得一个rpc客户端对象，此rpc client对象持有上下文消息的对象
        NettyRpcClient rpcClient = abstractRpcConnectManager.getNettyRpcClientByServerId(
                rpcContextHolderObject.getServiceId());
        //获得一个rpc请求消息生产工厂
        NettyRpcRequestFactory rpcRequestFactory =
                SpringServiceManager.getSpringLoadService().getNettyRpcRequestFactory();
        //构建一个rpc请求
        NettyRpcRequestMessage request =
                rpcRequestFactory.createNettyRpcRequestMessage(this.clazz.getName(), funcName, args);
        //将消息发送出去
        NettyRpcFuture rpcFuture = rpcClient.sendRequest(request);
        logger.info("正在接通远程服务PRC.是否完成:"+rpcFuture.isDone());
        return rpcFuture;
    }
}
