package com.wecloud.rtc.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.wecloud.im.entity.ImApplication;
import com.wecloud.im.entity.ImClient;
import com.wecloud.im.param.rtc.CandidateForwardParam;
import com.wecloud.im.param.rtc.CreateRtcChannelParam;
import com.wecloud.im.param.rtc.CreateRtcChannelResult;
import com.wecloud.im.param.rtc.JoinRtcChannelParam;
import com.wecloud.im.param.rtc.LeaveRtcChannelParam;
import com.wecloud.im.param.rtc.RejectRtcChannelParam;
import com.wecloud.im.param.rtc.SdpForwardParam;
import com.wecloud.im.service.ImApplicationService;
import com.wecloud.im.service.ImClientService;
import com.wecloud.im.ws.cache.UserStateCacheManager;
import com.wecloud.im.ws.cache.UserStateListener;
import com.wecloud.rtc.entity.response.RtcCallResponse;
import com.wecloud.rtc.entity.response.RtcCandidateForwardResponse;
import com.wecloud.rtc.entity.response.RtcClientJoinResponse;
import com.wecloud.rtc.entity.response.RtcClientLeaveResponse;
import com.wecloud.rtc.entity.response.RtcClientRejectResponse;
import com.wecloud.rtc.entity.response.RtcSdpForwardResponse;
import com.wecloud.rtc.service.MangerRtcCacheService;
import com.wecloud.rtc.service.RtcService;
import com.wecloud.rtc.service.WsRtcWrite;
import io.geekidea.springbootplus.framework.common.api.ApiResult;
import com.wecloud.utils.SnowflakeUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

@Slf4j
@Service
public class RtcServiceImpl extends UserStateListener implements RtcService {

    @Autowired
    private ImApplicationService imApplicationService;

    @Autowired
    private WsRtcWrite wsRtcWrite;

    /**
     * redis缓存
     */
    @Autowired
    private MangerRtcCacheService mangerRtcCacheService;

    @Autowired
    private ImClientService imClientService;

    @Autowired
    private UserStateCacheManager userStateCacheManager;

    @Override
    public void onLineEvent(Long client, Integer platform, String longChannelId) {
        // nothing need to do
    }

    @Override
    public void offlineEvent(Long clientId, Integer platform, String longChannelId) {
        //  根据appKey查询appid
        ImClient client = imClientService.getCacheImClient(clientId);

        // 获取该客户端加入的频道ID
        Long listByClientId = mangerRtcCacheService.getRtcChannelIdListByClientId(client.getId());
        if (listByClientId == null) {
            return;
        }

        LeaveRtcChannelParam leaveRtcChannelParam = new LeaveRtcChannelParam();
        leaveRtcChannelParam.setChannelId(listByClientId);
        // websocket离线逻辑  服务端踢出频道
        this.leave(leaveRtcChannelParam);
    }

    @Override
    public ApiResult<CreateRtcChannelResult> createAndCall(CreateRtcChannelParam createRtcChannelParam) throws JsonProcessingException {
        ImClient client = imClientService.getCurentClient();
        Long rtcChannelId = SnowflakeUtil.getId();

        //  判断发起方必须在线
        boolean onlineStatus = userStateCacheManager.isOnline(client.getId());
        if (!onlineStatus) {
            log.info("发起方必须在线" + client.getFkAppid() + client.getClientId());
            ApiResult.fail();
        }

        // 添加缓存
        mangerRtcCacheService.create(client.getId(), rtcChannelId);

        CreateRtcChannelResult createRtcChannelResult = new CreateRtcChannelResult();
        createRtcChannelResult.setChannelId(rtcChannelId);

        // ws向接收方发送通知
        RtcCallResponse rtcCallResponse = new RtcCallResponse();
        rtcCallResponse.setType(createRtcChannelParam.getType());
//        rtcCallResponse.setConversationId(createRtcChannelParam.getConversationId());
        rtcCallResponse.setChannelId(rtcChannelId);
        rtcCallResponse.setClientId(client.getClientId());
        rtcCallResponse.setTimestamp(System.currentTimeMillis());

        ImClient toClient = imClientService.getCacheImClient(client.getFkAppid(), createRtcChannelParam.getToClient());
        wsRtcWrite.rtcCall(rtcCallResponse, toClient.getId());

        // TODO 待开发 下发安卓和ios系统推送

        return ApiResult.ok(createRtcChannelResult);


    }

    @Override
    public ApiResult<Boolean> join(JoinRtcChannelParam joinRtcChannelParam) {

        ImClient client = imClientService.getCurentClient();

        // 修改缓存
        mangerRtcCacheService.join(client.getId(), joinRtcChannelParam.getChannelId());

        //获取频道内所有client
        List<String> clientListByRtcChannelId = mangerRtcCacheService.getClientListByRtcChannelId(joinRtcChannelParam.getChannelId());
        // 移除自己
        clientListByRtcChannelId.remove(client.getClientId());

        for (String toClientId : clientListByRtcChannelId) {

            // ws向接收方发送通知
            RtcClientJoinResponse rtcSdpForwardResponse = new RtcClientJoinResponse();

            rtcSdpForwardResponse.setChannelId(joinRtcChannelParam.getChannelId());
            rtcSdpForwardResponse.setClientId(client.getClientId());
            rtcSdpForwardResponse.setTimestamp(System.currentTimeMillis());
            wsRtcWrite.clientJoin(rtcSdpForwardResponse, Long.valueOf(toClientId));
        }

        return ApiResult.ok(true);
    }

    @Override
    public ApiResult<Boolean> reject(RejectRtcChannelParam rejectRtcChannelParam) {

        ImClient client = imClientService.getCurentClient();
        ImApplication imApplication = imApplicationService.getCacheById(client.getFkAppid());

        //获取频道内所有client
        List<String> clientListByRtcChannelId = mangerRtcCacheService.getClientListByRtcChannelId(rejectRtcChannelParam.getChannelId());
        // 移除自己
        clientListByRtcChannelId.remove(client.getClientId());


        for (String toClientId : clientListByRtcChannelId) {

            // ws向接收方发送通知
            RtcClientRejectResponse rtcClientRejectResponse = new RtcClientRejectResponse();

            rtcClientRejectResponse.setChannelId(rejectRtcChannelParam.getChannelId());
            rtcClientRejectResponse.setClientId(client.getClientId());
            rtcClientRejectResponse.setTimestamp(System.currentTimeMillis());
            wsRtcWrite.clientReject(rtcClientRejectResponse, Long.valueOf(toClientId));
        }
        return ApiResult.ok(true);
    }

    @Override
    public ApiResult<Boolean> leave(LeaveRtcChannelParam leaveRtcChannelParam) {

        ImClient client = imClientService.getCurentClient();

        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getCacheById(client.getFkAppid());
        this.leave(leaveRtcChannelParam, client);

        return ApiResult.ok(true);
    }

    private void leave(LeaveRtcChannelParam leaveRtcChannelParam, ImClient client) {
        // 修改缓存
        mangerRtcCacheService.leave(client.getId(), leaveRtcChannelParam.getChannelId());

        //获取频道内所有client
        List<String> clientListByRtcChannelId = mangerRtcCacheService.getClientListByRtcChannelId(leaveRtcChannelParam.getChannelId());
        // 移除自己
        clientListByRtcChannelId.remove(client.getClientId());

        for (String toClientId : clientListByRtcChannelId) {

            // ws向接收方发送通知
            RtcClientLeaveResponse rtcClientLeaveResponse = new RtcClientLeaveResponse();

            rtcClientLeaveResponse.setChannelId(leaveRtcChannelParam.getChannelId());
            rtcClientLeaveResponse.setClientId(client.getClientId());
            rtcClientLeaveResponse.setTimestamp(System.currentTimeMillis());
            wsRtcWrite.clientLeave(rtcClientLeaveResponse, Long.valueOf(toClientId));
        }

        // 判断频道内是否无其他人了
        if (mangerRtcCacheService.channelIsEmpty(leaveRtcChannelParam.getChannelId())) {
            // 移除频道信息
            mangerRtcCacheService.delChannelInfo(leaveRtcChannelParam.getChannelId());
        }
    }

    @Override
    public ApiResult<Boolean> sdpForward(SdpForwardParam sdpForwardParam) {

        ImClient client = imClientService.getCurentClient();
        Long rtcChannelId = SnowflakeUtil.getId();

        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getCacheById(client.getFkAppid());

        //  判断发起方必须在线
        boolean onlineStatus = userStateCacheManager.isOnline(client.getId());
        if (!onlineStatus) {
            log.info("发起方必须在线" + imApplication.getAppKey() + client.getClientId());
            ApiResult.fail();
        }

        CreateRtcChannelResult createRtcChannelResult = new CreateRtcChannelResult();
        createRtcChannelResult.setChannelId(rtcChannelId);

        //获取频道内所有client
        List<String> clientListByRtcChannelId = mangerRtcCacheService.getClientListByRtcChannelId(sdpForwardParam.getChannelId());
        // 移除自己
        clientListByRtcChannelId.remove(client.getClientId());

        for (String toClientId : clientListByRtcChannelId) {

            // ws向接收方发送通知
            RtcSdpForwardResponse rtcSdpForwardResponse = new RtcSdpForwardResponse();
            rtcSdpForwardResponse.setSdpData(sdpForwardParam.getSdpData());
            rtcSdpForwardResponse.setSdpType(sdpForwardParam.getSdpType());

            rtcSdpForwardResponse.setChannelId(rtcChannelId);
            rtcSdpForwardResponse.setClientId(client.getClientId());
            rtcSdpForwardResponse.setTimestamp(System.currentTimeMillis());
            wsRtcWrite.sdpForward(rtcSdpForwardResponse, Long.valueOf(toClientId));
        }


        return ApiResult.ok(true);
    }

    @Override
    public ApiResult<Boolean> candidateForward(CandidateForwardParam candidateForwardParam) {

        ImClient client = imClientService.getCurentClient();
        Long rtcChannelId = SnowflakeUtil.getId();

        //  根据appKey查询appid
        ImApplication imApplication = imApplicationService.getCacheById(client.getFkAppid());

        //  判断发起方必须在线
        boolean onlineStatus = userStateCacheManager.isOnline(client.getId());
        if (!onlineStatus) {
            log.info("发起方必须在线" + imApplication.getAppKey() + client.getClientId());
            ApiResult.fail();
        }

        CreateRtcChannelResult createRtcChannelResult = new CreateRtcChannelResult();
        createRtcChannelResult.setChannelId(rtcChannelId);

        //获取频道内所有client
        List<String> clientListByRtcChannelId = mangerRtcCacheService.getClientListByRtcChannelId(candidateForwardParam.getChannelId());
        // 移除自己
        clientListByRtcChannelId.remove(client.getClientId());

        for (String toClientId : clientListByRtcChannelId) {

            // ws向接收方发送通知
            RtcCandidateForwardResponse rtcCandidateForwardResponse = new RtcCandidateForwardResponse();

            rtcCandidateForwardResponse.setCandidateData(candidateForwardParam.getCandidateData());

            rtcCandidateForwardResponse.setChannelId(rtcChannelId);
            rtcCandidateForwardResponse.setClientId(client.getClientId());
            rtcCandidateForwardResponse.setTimestamp(System.currentTimeMillis());
            wsRtcWrite.candidateForward(rtcCandidateForwardResponse, Long.valueOf(toClientId));
        }

        return ApiResult.ok(true);
    }
}
