package com.sjyt.icom.asst.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import com.sjyt.icom.asst.common.enums.ErrorCodeEnum;
import com.sjyt.icom.asst.common.enums.MsgTypeEnum;
import com.sjyt.icom.asst.common.model.message.Message;
import com.sjyt.icom.asst.common.model.message.News;
import com.sjyt.icom.asst.common.model.room.SrsUrlObj;
import com.sjyt.icom.asst.common.model.sdp.RespError;
import com.sjyt.icom.asst.common.model.sdp.RespJoin;
import com.sjyt.icom.asst.common.model.sdp.RespLeave;
import com.sjyt.icom.asst.common.util.JsonUtils;
import com.sjyt.icom.asst.endpoint.BeanResolvable;
import com.sjyt.icom.asst.service.ISendMessage;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;

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

/**
 * <p>发送消息服务基类</p>
 *
 * @author renyanru
 * @version V1.0.0
 * @date 2022/6/24 14:22
 */
@Slf4j
@AllArgsConstructor
public abstract class BaseSendMsgService implements ISendMessage<News> {
    private final BeanResolvable beanResolvable;
    @Async
    @Override
    public void send(Set<String> ids, News news) {
        ids.stream().filter(id -> ObjectUtil.notEqual(id, news.getFrom())).forEach(it -> send(it, news));
    }

    @Async
    @Override
    public void send(String uid, News news) {
        chPoolService.getChannel(uid).ifPresent(
                channel -> channel.writeAndFlush(new TextWebSocketFrame(JsonUtils.pojoToJson(news))));
    }

    /**
     * 发送离开通知
     *
     * @param ids 个人节点地址
     */
    @Async
    public void sendForLeave(String... ids) {
        for (String id : ids) {
            chPoolService.getChannel(id).ifPresent(it -> send(it, leave(id)));
        }
    }

    public void sendForJoin(ExtraInfo... extraInfos) {
        for (ExtraInfo info : extraInfos) {
            chPoolService.getChannel(info.getUid()).ifPresent(it -> send(it, join(info.getUrlObj())));
        }
    }

    /**
     * 发送错误信息
     *
     * @param code      错误码
     * @param errorText 内容
     */
    @Async
    public void sendForError(String uid, String code, String errorText) {
        chPoolService.getChannel(uid).ifPresent(it -> send(it, error(code, errorText)));
    }

    @Async
    public void sendForError(String uid, ErrorCodeEnum errorCodeEnum) {
        sendForError(uid, errorCodeEnum.getCode(), errorCodeEnum.getVALUE());
    }

    @Override
    @Async
    public void send(Channel ch, News news) {
        ch.writeAndFlush(new TextWebSocketFrame(JsonUtils.pojoToJson(news)));
        log.info("{}--发送了消息", ch.id());
        log.info("在自定义线程" + Thread.currentThread().getName() + "执行了");
    }

    @Async
    public void send2To(News news) {
        chPoolService.getChannel(news.getTo()).ifPresent(it -> send(it, news));
    }

    @Async
    public void send2From(News news) {
        chPoolService.getChannel(news.getFrom()).ifPresent(it -> send(it, news));
    }

    /**
     * 得到错误消息体
     *
     * @param code      错误码
     * @param errorText 错误提示内容
     * @return r
     */
    public RespError getError(String code, String errorText) {
        return RespError.builder().code(code).msg(errorText).msgType(MsgTypeEnum.RespError.getCODE()).build();
    }

    /**
     * 通用NewsLetter
     *
     * @param from from
     * @param to   to
     * @param cmd  cmd
     * @return news
     */
    public News newsLetter(String from, String to, String cmd) {
        News.NewsLetterBuilder builder = News.builder();
        builder.from(from).to(to);
        Message message = Message.builder().build();
        message.setCmd(cmd);
        return builder.message(message).build();
    }

    /**
     * 得到错误消息体
     *
     * @param errorCodeEnum 错误枚举
     * @return r
     */
    public RespError getError(ErrorCodeEnum errorCodeEnum) {
        return getError(errorCodeEnum.getCode(), errorCodeEnum.getVALUE());
    }

    private News newsLetter() {
        News.NewsLetterBuilder builder = News.builder();
        Message message = Message.builder().build();
        return builder.message(message).build();
    }


    private News leave(String uid) {
        News news = newsLetter();
        Message message = news.getMessage();
        RespLeave respLeave = RespLeave.builder().to(uid).msgType(MsgTypeEnum.RespLeave.getCODE()).build();
        message.setBody(BeanUtil.beanToMap(respLeave));
        return news;
    }

    private News join(SrsUrlObj urlSrs) {
        News news = newsLetter();
        Message message = news.getMessage();
        RespJoin respJoin = RespJoin.builder().streamUrls(urlSrs).msgType(MsgTypeEnum.RespJoin.getCODE()).build();
        message.setBody(BeanUtil.beanToMap(respJoin));
        return news;
    }

    private News error(String code, String errorText) {
        News news = newsLetter();
        Message message = news.getMessage();
        RespError respError = RespError.builder().code(code).msg(errorText).msgType(MsgTypeEnum.RespError.getCODE()).build();
        message.setBody(BeanUtil.beanToMap(respError));
        return news;
    }
}
