package com.wecloud.im.ws.service.impl;

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.wecloud.im.router.RouterSendService;
import com.wecloud.im.ws.cache.UserCacheService;
import com.wecloud.im.ws.model.WsResponseModel;
import com.wecloud.im.ws.model.redis.ClientChannelInfo;
import com.wecloud.im.ws.model.request.ReceiveVO;
import com.wecloud.im.ws.service.MangerChannelService;
import com.wecloud.im.ws.service.WriteDataService;
import com.wecloud.im.ws.utils.InitIp;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ThreadFactory;

/**
 * @Description 下发数据
 * @Author hewei hwei1233@163.com
 * @Date 2019-12-05
 */
@Component
public class WriteDataServiceImpl implements WriteDataService {

    private final static ThreadFactory WRITE_NAMED_THREAD_FACTORY = new ThreadFactoryBuilder()
            .setNamePrefix("ws-WRITE-").build();
    /**
     * 耗时核心业务处理线程池
     * 属于io密集型业务
     * io密集型任务配置尽可能多的线程数量
     */
//    private final static ExecutorService WRITE_TASK_THREAD_POOL_EXECUTOR =
//            new ThreadPoolExecutor(WsConstants.CPU_PROCESSORS * 2, WsConstants.CPU_PROCESSORS * 3,
//                    1L, TimeUnit.MILLISECONDS,
//                    new LinkedBlockingQueue<Runnable>(), WRITE_NAMED_THREAD_FACTORY, new ThreadPoolExecutor.CallerRunsPolicy());

    @Autowired
    private MangerChannelService mangerChannelService;


    @Autowired
    private UserCacheService userCacheService;

    @Autowired
    private RouterSendService routerSendService;

    @Override
    public void successAndData(ReceiveVO receiveVO, Object data, String toAppKey, String toClientId) {
        this.dataAndStatus(receiveVO, ApiCode.SUCCESS, data, toAppKey, toClientId);
    }

    @Override
    public void nullDataSuccess(ReceiveVO receiveVO, ApiCode apiCode, String toAppKey, String toClientId) {
        this.dataAndStatus(receiveVO, apiCode, new HashMap<>(1), toAppKey, toClientId);
    }

    @Override
    public void paramErrorAndNullData(ReceiveVO receiveVO, String toAppKey, String toClientId) {
//        this.nullDataSuccess(requestModel, ResultStatus.PARAM_ERROR, userId);
    }


    @Override
    public void dataAndStatus(ReceiveVO receiveVO, ApiCode apiCode, Object data, String toAppKey, String toClientId) {
        ApiResult<Boolean> apiResult = ApiResult.result(apiCode);
        WsResponseModel responseModel = new WsResponseModel();
        responseModel.setMsg(apiResult.getMessage());
        responseModel.setCmd(receiveVO.getCmd());
        responseModel.setReqId(receiveVO.getReqId());
        responseModel.setData(data);
        responseModel.setCode(apiResult.getCode());
        this.write(responseModel, toAppKey, toClientId);
    }


    @Override
    public void write(WsResponseModel responseModel, String toAppKey, String toClientId) {

        String msgJson = JsonUtils.encodeJson(responseModel);

        List<ClientChannelInfo> channelInfos = userCacheService.getIpByClientIdAndOnline(toAppKey, toClientId);

        for (ClientChannelInfo channelInfo : channelInfos) {

            // 是否为当前机器的ip
            if (InitIp.lAN_IP.equals(channelInfo.getLanIp())) {
                // 调用本地下发
                mangerChannelService.writeDataToChannel(msgJson, channelInfo.getChannelId());

            } else {
                // rpc调用下发
                routerSendService.rpcSend(msgJson, channelInfo.getChannelId());
            }

        }

    }

    @Override
    public void response(WsResponseModel responseModel, NioSocketChannel nioSocketChannel) {

        String msgJson = JsonUtils.encodeJson(responseModel);

        // 本地直接下发
        nioSocketChannel.writeAndFlush(new TextWebSocketFrame(msgJson));
    }

}
