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

import cn.hutool.core.thread.ThreadFactoryBuilder;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.json.JsonMapper;
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.ReceiveModel;
import com.wecloud.im.ws.service.MangerChannelService;
import com.wecloud.im.ws.service.WriteDataService;
import com.wecloud.im.ws.utils.InitIp;
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(ReceiveModel receiveModel, Object data, String toAppKey, String toClientId) {
        this.dataAndStatus(receiveModel, ApiCode.SUCCESS, data, toAppKey, toClientId);
    }

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

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


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

//    @Override
//    public void write(WsResponseModel responseModel, String toAppKey, String toClientId) {
////        WRITE_TASK_THREAD_POOL_EXECUTOR.execute(
////                () -> {
//        JsonMapper jsonMapper = new JsonMapper();
//        String json = null;
//        try {
//            json = jsonMapper.writeValueAsString(responseModel);
//        } catch (JsonProcessingException e) {
//            e.printStackTrace();
//        }
//        mangerChannelService.writeData(json, toAppKey, toClientId);
//    }
//        );
//}


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

        JsonMapper jsonMapper = new JsonMapper();
        String msgJson = null;

        try {
            msgJson = jsonMapper.writeValueAsString(responseModel);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        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) {

        JsonMapper jsonMapper = new JsonMapper();
        String msgJson = null;

        try {
            msgJson = jsonMapper.writeValueAsString(responseModel);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

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

}
