package com.wecloud.im.ws.strategy;

import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.enums.ChatTypeEnum;
import com.wecloud.im.param.ImConversationQueryVo;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.service.ImConversationService;
import com.wecloud.im.ws.enums.WsRequestCmdEnum;
import com.wecloud.im.ws.model.request.PushVO;
import com.wecloud.im.ws.model.request.ReceiveDataVO;
import com.wecloud.im.ws.model.request.ReceiveVO;
import com.wecloud.im.ws.utils.SpringBeanUtils;
import com.wecloud.utils.JsonUtils;
import io.netty.channel.ChannelHandlerContext;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;

import static com.wecloud.im.ws.ImConstant.DATA;
import static com.wecloud.im.ws.ImConstant.MSG_TYPE;
import static com.wecloud.im.ws.ImConstant.PUSH_BODY;
import static com.wecloud.im.ws.ImConstant.PUSH_KEY;
import static com.wecloud.im.ws.ImConstant.PUSH_TITLE;
import static com.wecloud.im.ws.ImConstant.SUB_TITLE;
import static com.wecloud.im.ws.ImConstant.TITLE;
import static com.wecloud.im.ws.ImConstant.TO_CONVERSATION_KEY;

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

    private static volatile ImCmdStrategyFactory imCmdStrategyFactory;
    private static ImApplicationService imApplicationService;
    private static ImClientService imClientService;
    private static ImConversationService imConversationService;

    public static void process(Long senderClientId, ChannelHandlerContext ctx, String data) {
        if (log.isDebugEnabled()) {
            log.debug("appWS收到data: {}\n senderClientId:{}, channelId:{}", data, senderClientId, 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);
                    imConversationService = SpringBeanUtils.getBean(ImConversationService.class);
                }
            }
        }

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

        // 参数判空校验
        if (paramCheck(receiveVO)) {
            return;
        }

        Long toConversationId = Long.valueOf(receiveVO.getData().get(TO_CONVERSATION_KEY).toString());
        Integer type = Integer.valueOf(receiveVO.getData().get(MSG_TYPE).toString());

        // 移除后端固定的字段,其余字段都为第三方应用定义的,需要作为可拓展的json传入数据库
        // 因mysql关系型数据库非MongoDB文档类型数据库,第三方应用拓展的参数值需要使用json格式落库
        receiveVO.getData().remove(MSG_TYPE);
        receiveVO.getData().remove(TO_CONVERSATION_KEY);

        // 获取自定义推送字段 (可选)
        HashMap<String, Object> pushMap = getPushMap(receiveVO);

        // 内部固定参数model
        ReceiveDataVO sysParam = new ReceiveDataVO();
        sysParam.setPushVO(getPushModel(pushMap));
        sysParam.setToConversation(toConversationId);
        sysParam.setType(type);

        //查看接收的群属性，是否万人群
        ImConversationQueryVo conversation = imConversationService.getCacheImConversationById(toConversationId);

        if (conversation == null) {
            log.warn("会reqId: {} ,会话id: {}db中不存在", receiveVO.getReqId(), toConversationId);
            return;
        }

        WsRequestCmdEnum wsRequestPathEnum = WsRequestCmdEnum.getByCode(receiveVO.getCmd());
        if (ChatTypeEnum.THOUSAND_GROUP.getCode().equals(conversation.getChatType()) && WsRequestCmdEnum.NORMAL_CHAT == wsRequestPathEnum) {
            // 普通群升级为万人群
            wsRequestPathEnum = WsRequestCmdEnum.THROUSAND_CHAT;
        }
        // 使用策略模式， 根据不同类型请求调用不同实现类
        AbstractImCmdStrategy cmdStrategy = imCmdStrategyFactory.getStrategy(wsRequestPathEnum);

        // 查询发送者client
        ImClient imClientSender = imClientService.getCacheImClient(senderClientId);
        if (imClientSender == null) {
            log.warn("根据senderClientId: {} 查找不到 imClientSender！", senderClientId);
            return;
        }

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

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

    }


    /**
     * 封装推送实体
     *
     * @param pushMap
     * @return
     */
    private static PushVO getPushModel(HashMap<String, Object> pushMap) {
        PushVO pushModel = new PushVO();
        if (pushMap == null || pushMap.isEmpty()) {
            pushModel.setTitle(PUSH_TITLE);
            pushModel.setSubTitle(PUSH_BODY);
            pushModel.setData(new HashMap<>(1));
        } else {
            pushModel.setTitle((String) pushMap.get(TITLE));
            pushModel.setSubTitle((String) pushMap.get(SUB_TITLE));

            // 自定义推送内容
            HashMap hashMap = (HashMap) pushMap.get(DATA);
            pushModel.setData(hashMap);
        }

        return pushModel;
    }

    /**
     * 获取自定义推送字段
     *
     * @param receiveVO
     * @return
     */
    private static HashMap<String, Object> getPushMap(ReceiveVO receiveVO) {
        HashMap<String, Object> pushMap = null;
        if (receiveVO.getData().get(PUSH_KEY) != null) {
            pushMap = (HashMap<String, Object>) receiveVO.getData().get(PUSH_KEY);
            receiveVO.getData().remove(PUSH_KEY);
        }
        return pushMap;
    }

    /**
     * 参数判空校验
     *
     * @param receiveVO
     * @return
     */
    private static boolean paramCheck(ReceiveVO receiveVO) {
        if (receiveVO == null) {
            log.warn("receiveVO == null 不合法 ");
            return true;
        }
        if (receiveVO.getReqId() == null) {
            log.warn("receiveVO.getReqId() == null 不合法");
            return true;
        }
        if (receiveVO.getData() == null || receiveVO.getData().isEmpty()) {
            log.warn("receiveVO.getData() null 不合法 reqId: {}", receiveVO.getReqId());
            return true;
        }
        // 获取会话id(必传)
        if (receiveVO.getData().get(TO_CONVERSATION_KEY) == null) {
            log.warn("reqId: {} 不合法，缺少会话id！", receiveVO.getReqId());
            return true;
        }
        // 获取消息type(必传)
        if (receiveVO.getData().get(MSG_TYPE) == null) {
            log.warn("reqId: {} 不合法，缺少消息type！", receiveVO.getReqId());
            return true;
        }
        return false;
    }

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