package com.wecloud.im.ws.strategy;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.enums.WsRequestCmdEnum;
import com.wecloud.im.ws.model.request.ReceiveVO;
import com.wecloud.im.ws.utils.SpringBeanUtils;
import com.wecloud.utils.JsonUtils;
import io.geekidea.springbootplus.framework.common.exception.BusinessException;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

/**
 * @Description 处理Cmd请求
 * 抽象类 策略设计模式
 * @Author hewei hwei1233@163.com
 * @Date 2020-01-02
 */
@Slf4j
public abstract class AbstractImCmdStrategy {

    private static ImCmdStrategyFactory imCmdStrategyFactory;
    private static ImApplicationService imApplicationService;
    private static ImClientService imClientService;

    public static void process(String appKey, String clientId, ChannelHandlerContext ctx, String data) throws JsonProcessingException {
        if(log.isDebugEnabled()) {
            log.debug("appWS收到data: {}\n appKey:{}, clientId:{}, channelId:{}", data, appKey, clientId, ctx.channel().id().asLongText());
        }

        if(imCmdStrategyFactory == null) {
            synchronized (AbstractImCmdStrategy.class) {
                // 双空判断，懒汉模式下的绝对线程安全
                if(imCmdStrategyFactory == null) {
                    imCmdStrategyFactory = SpringBeanUtils.getBean(ImCmdStrategyFactory.class);
                    imApplicationService = SpringBeanUtils.getBean(ImApplicationService.class);
                    imClientService = SpringBeanUtils.getBean(ImClientService.class);
                }
            }
        }

        // 解析jsonO
        ReceiveVO receiveVO = JsonUtils.decodeJson(data, ReceiveVO.class);


        if (null == receiveVO || null == receiveVO.getCmd()) {
            throw new BusinessException("null == receiveVO || null == receiveVO.getCmd()");
        }

        WsRequestCmdEnum wsRequestPathEnum = WsRequestCmdEnum.getByCode(receiveVO.getCmd());
        // 使用策略模式， 根据不同类型请求调用不同实现类
        AbstractImCmdStrategy cmdStrategy = imCmdStrategyFactory.getStrategy(wsRequestPathEnum);

        // 查询imApplication
        ImApplication imApplication = imApplicationService.getOneByAppKey(appKey);
        if (imApplication == null) {
            log.warn("根据appKey: {} 查找不到 imApplication！", appKey);
            return;
        }

        // 查询发送者client
        ImClient imClientSender = imClientService.getOne(new QueryWrapper<ImClient>().lambda()
                .eq(ImClient::getFkAppid, imApplication.getId())
                .eq(ImClient::getClientId, clientId));
        if (imClientSender == null) {
            log.warn("根据appKey: {} 查找不到 imClientSender！", imApplication.getAppKey());
            return;
        }

        cmdStrategy.process(imApplication, imClientSender, ctx, receiveVO);

    }

    /**
     * 处理业务流程
     *
     * @param imApplication
     * @param imSender
     * @param ctx
     * @param receiveVO
     * @throws Exception
     */
    public abstract void process(ImApplication imApplication, ImClient imSender, ChannelHandlerContext ctx, ReceiveVO receiveVO);
}
