package com.twjitm.core.common.service.rpc.network;

import com.twjitm.core.common.netstack.entity.rpc.NettyRpcRequestMessage;
import com.twjitm.core.common.netstack.entity.rpc.NettyRpcResponseMessage;
import com.twjitm.core.common.service.rpc.client.NettyRpcFuture;
import com.twjitm.core.common.service.rpc.server.NettyRpcNodeInfo;
import com.twjitm.core.common.service.rpc.service.NettyRPCFutureService;
import com.twjitm.core.spring.SpringServiceManager;
import com.twjitm.core.utils.logs.LoggerUtils;
import io.netty.channel.socket.nio.NioSocketChannel;
import org.apache.log4j.Logger;

import java.util.concurrent.ExecutorService;

/**
 * @author twjitm - [Created on 2018-08-20 11:01]
 * @company https://github.com/twjitm/
 * @jdk java version "1.8.0_77"
 * netty rpc client entity
 */
public class NettyRpcClient {

    private Logger logger = LoggerUtils.getLogger(NettyRpcClient.class);
    private NettyRpcClientConnection rpcClientConnection;


    public NettyRpcClient(NettyRpcNodeInfo rpcNodeInfo, ExecutorService threadPool) {
        rpcClientConnection = new NettyRpcClientConnection(this, rpcNodeInfo, threadPool);
    }

    /**
     * 发送消息，最终会调用rpcClientConnection 的writeRequest方法。其实内部实现
     * 则利用netty 的channel对象发送数据
     *
     * @param request
     * @return
     */
    public NettyRpcFuture sendRequest(NettyRpcRequestMessage request) {
        NettyRpcFuture rpcFuture = new NettyRpcFuture(request);
        NettyRPCFutureService rpcFutureService = SpringServiceManager.getSpringLoadService().getNettyRPCFutureService();
        rpcFutureService.addNettyRPCFuture(request.getRequestId(), rpcFuture);
        //发送数据到远程服务器上
        rpcClientConnection.sendRequestMessage(request);
        return rpcFuture;
    }

    public NioSocketChannel getChannel() {
        return rpcClientConnection.getChannel();
    }

    public void close() {
        logger.info("RPC CLIENT CLOSE");
        if (rpcClientConnection != null) {
            rpcClientConnection.close();
        }
    }

    /**
     * 本地调用对象处理rpc返回消息
     *
     * @param rpcResponse
     */
    public void handleRpcResponse(NettyRpcResponseMessage rpcResponse) {
        String requestId = rpcResponse.getRequestId();
        NettyRPCFutureService rpcFutureService = SpringServiceManager.getSpringLoadService().
                getNettyRPCFutureService();
        NettyRpcFuture rpcFuture = rpcFutureService.getNettyRPCFuture(requestId);
        if (rpcFuture != null) {
            boolean removeFlag = rpcFutureService.removeNettyRPCFuture(requestId, rpcFuture);
            if (removeFlag) {
                rpcFuture.done(rpcResponse);
            } else {
                //表示服务器已经处理过了,可能已经超时了
                logger.error("RPC FUTURE IS REMOVE " + requestId);
            }
        }
    }

    public NettyRpcClientConnection getRpcClientConnection() {
        return rpcClientConnection;
    }

}
