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.ws.model.ResponseModel;
import com.wecloud.im.ws.model.WsConstants;
import com.wecloud.im.ws.model.request.ReceiveModel;
import com.wecloud.im.ws.service.MangerChannelService;
import com.wecloud.im.ws.service.WriteDataService;
import io.geekidea.springbootplus.framework.common.api.ApiCode;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @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 * 10, WsConstants.CPU_PROCESSORS * 500,
                    1L, TimeUnit.MILLISECONDS,
                    new LinkedBlockingQueue<Runnable>(), WRITE_NAMED_THREAD_FACTORY, new ThreadPoolExecutor.CallerRunsPolicy());

    @Autowired
    private MangerChannelService mangerChannelService;

    @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);
        ResponseModel responseModel = new ResponseModel();
        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(ResponseModel 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);

                }
        );


    }

}
