package com.yonge.cooleshow.biz.dal.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginContext;
import com.microsvc.toolkit.middleware.rtc.RTCRoomPluginService;
import com.microsvc.toolkit.middleware.rtc.impl.TencentCloudRTCPlugin;
import com.microsvc.toolkit.middleware.rtc.message.RTCRoomConfig;
import com.yonge.cooleshow.biz.dal.dao.ImNetworkRoomDao;
import com.yonge.cooleshow.biz.dal.dto.ImNetworkDisplayDataDto;
import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoom;
import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMember;
import com.yonge.cooleshow.biz.dal.entity.ImNetworkRoomMemberStatus;
import com.yonge.cooleshow.biz.dal.enums.RoleEnum;
import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberService;
import com.yonge.cooleshow.biz.dal.service.ImNetworkRoomMemberStatusService;
import com.yonge.cooleshow.biz.dal.service.ImService;
import com.yonge.cooleshow.biz.dal.service.RoomService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;

/**
 * 网络教室房间(ImNetworkRoom)表服务实现类
 *
 * @author zx
 * @since 2022-03-30 16:36:36
 */
@Service("roomService")
public class RoomServiceImpl extends ServiceImpl<ImNetworkRoomDao, ImNetworkRoom> implements RoomService {

    private final static Logger log = LoggerFactory.getLogger(RoomServiceImpl.class);

    @Autowired
    private RTCRoomPluginContext rtcRoomPluginContext;
    @Autowired
    private ImNetworkRoomMemberStatusService imNetworkRoomMemberStatusService;
    @Autowired
    private ImNetworkRoomMemberService imNetworkRoomMemberService;
    @Autowired
    private ImService imService;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;

    @Override
    public ImNetworkRoomDao getDao() {
        return baseMapper;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ImNetworkRoom initRoom(String roomId, RoleEnum userRole, String imUserId) {
        ImNetworkRoom room = baseMapper.findByRoomId(roomId);
        String display = "";
        if (userRole == RoleEnum.RoleTeacher) {
            display = "display://type=1?userId=" + imUserId + "?uri=";
        }
        if(Objects.isNull(room)){
            room = new ImNetworkRoom();
            //创建房间
            room.setRoomId(roomId);
            room.setDisplay(display);
            baseMapper.insert(room);
        }else {
            if(userRole == RoleEnum.RoleTeacher){
                room.setDisplay(display);
                baseMapper.updateById(room);
            }
        }
        return room;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RTCRoomConfig getRtcRoomConfig(String serviceProvider, ImNetworkRoomMember roomMember) {
        RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
        if (TencentCloudRTCPlugin.PLUGIN_NAME.equals(serviceProvider) || StringUtils.isEmpty(serviceProvider)) {
            // 腾讯云RTC
            // 用户IM帐号创建
            try {
                pluginService.register(roomMember.getUserId(), roomMember.getUserName(), roomMember.getAvatar());
            } catch (Exception e) {
                log.error("直播房间用户注册失败: userId={}", roomMember.getUserId(), e);
            }
            return rtcRoomPluginContext.getPluginService().getRTCRoomConfig(roomMember.getUserId());
        }
        return new RTCRoomConfig();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void quitRoomSuccess(RoleEnum roleEnum,String imUserId,String roomId,String serviceProvider) throws Exception {
        ImNetworkRoom room = baseMapper.findByRoomId(roomId);
        if (roleEnum == RoleEnum.RoleTeacher){
            //如果老师退出房间，初始化节拍器和伴奏播放配置
            imNetworkRoomMemberStatusService.lambdaUpdate().eq(ImNetworkRoomMemberStatus::getRoomId,roomId)
                    .set(ImNetworkRoomMemberStatus::getPlayMidi,null)
                    .set(ImNetworkRoomMemberStatus::getMusicSheetDownloadJson,null).update();
            if (isUserDisplay(room.getDisplay(),imUserId)) {
                room.setDisplay("");
                ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery()
                        .eq(ImNetworkRoomMember::getRoomId, roomId)
                        .eq(ImNetworkRoomMember::getRole, RoleEnum.RoleTeacher.getValue())
                        .eq(ImNetworkRoomMember::getUserId, imUserId).last("limit 1").one();
                this.updateDisplay(roomMember,room,serviceProvider);
            }
        }
        int memberNum = imNetworkRoomMemberService.lambdaQuery()
                .eq(ImNetworkRoomMember::getRoomId,roomId).count();
        if (memberNum <= 1) {
            RTCRoomPluginService pluginService = rtcRoomPluginContext.getPluginService(serviceProvider);
            redisTemplate.delete("joinImGroup:" + roomId);
            pluginService.chatRoomDestroy(roomId);
            //删除房间
            this.removeById(room.getId());
            //删除房间用户
            imNetworkRoomMemberService.lambdaUpdate().eq(ImNetworkRoomMember::getRoomId,roomId).remove();
            log.info("leaveRoomSuccess dismiss the room: {},userId: {}", roomId, imUserId);
        } else {
            ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery().eq(ImNetworkRoomMember::getRoomId, roomId)
                    .eq(ImNetworkRoomMember::getUserId, imUserId)
                    .eq(ImNetworkRoomMember::getRole, roleEnum.getValue())
                    .last("limit 1").one();
            if(roomMember != null){
                imService.sendQuitRoomMsg(roomMember,serviceProvider);
                imNetworkRoomMemberService.removeById(roomMember.getId());
            }
            log.info("leaveRoomSuccess quit group: roomId={},userId: {}", roomId,imUserId);
        }
    }

    //修改节拍器
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDisplay(ImNetworkRoomMember roomMember, ImNetworkRoom room, String serviceProvider) throws Exception {
        baseMapper.updateById(room);
        //节拍器修改消息发送
        imService.sendDisplay(roomMember,room,serviceProvider);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void display(ImNetworkDisplayDataDto displayData,String serviceProvider) throws Exception {
        StringBuffer display = new StringBuffer("display://type=").append(displayData.getType().ordinal()).append("?userId=");
        switch (displayData.getType()) {
            case NONE:
                //清空当前 room 的 display
                display = new StringBuffer();
                break;
            case TEACHER:
            case SCREEN:
                display.append(displayData.getTeacherId()).append("?uri=");
                break;
            case STUDENT:
                display.append(displayData.getUserId()).append("?uri=").append(displayData.getUri());
                break;
            default:
                display.append(displayData.getTeacherId()).append("?uri=").append(displayData.getUri());
                break;
        }
        ImNetworkRoom room = baseMapper.findByRoomId(displayData.getRoomId());
        room.setDisplay(display.toString());

        ImNetworkRoomMember roomMember = imNetworkRoomMemberService.lambdaQuery()
                .eq(ImNetworkRoomMember::getRoomId, displayData.getRoomId())
                .eq(ImNetworkRoomMember::getRole, RoleEnum.RoleTeacher.getValue())
                .eq(ImNetworkRoomMember::getUserId, displayData.getTeacherId()).last("limit 1").one();
        this.updateDisplay(roomMember,room,serviceProvider);
    }

    public boolean isUserDisplay(String display, String imUserId) {
        boolean result = false;
        if (!display.isEmpty() && display.contains("userId=" + imUserId)) {
            if (display.contains("type=0") || display.contains("type=1") || display.contains("type=3")) {
                result = true;
            }
        }
        return result;
    }
}