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

import cn.hutool.core.util.ObjectUtil;
import com.sjyt.icom.asst.common.enums.MsgTypeEnum;
import com.sjyt.icom.asst.common.enums.RoomEnum;
import com.sjyt.icom.asst.common.model.message.NewsLetter;
import com.sjyt.icom.asst.common.model.room.Room;
import com.sjyt.icom.asst.common.model.room.SrsUrlObj;
import com.sjyt.icom.asst.common.model.sdp.*;
import com.sjyt.icom.asst.common.util.JsonUtils;
import com.sjyt.icom.asst.conf.properties.RtspAppProperties;
import com.sjyt.icom.asst.context.handle.room.RoomFactory;
import com.sjyt.icom.asst.context.handle.room.RoomFactoryHandleEvent;
import com.sjyt.icom.asst.service.ISrsRpcService;
import com.sjyt.icom.asst.service.httpapi.SrsHttpApi;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;

/**
 * SrsRpc远程调用
 *
 * @author: Tab
 * @date: 2022-06-11 22:49
 * @since 1.0.0
 */
@Slf4j
@Service
@AllArgsConstructor
public class SrsRpcService implements ISrsRpcService {
    private final RtspAppProperties config;
    private final SrsHttpApi srsApi;
    private final RoomFactory roomFactoryContext;

    /**
     * 推拉流sdp
     *
     * @param news @return r
     */
    @Override
    public CompletableFuture<FutureAnswer> sdp(NewsLetter news) {
        return srsRpc(news);
    }

    private CompletableFuture<FutureAnswer> srsRpc(NewsLetter news) {
        //推拉 or 拉流
        ReqOffer reqOffer = JsonUtils.jsonToPojo(JsonUtils.pojoToJson(news.getMessage().getBody()), ReqOffer.class);
        Optional<SrsUrlObj> optionalStreamUrlSrs = getSrsUrlObj(news, reqOffer);
        final SrsUrlObj srsUrlObj = optionalStreamUrlSrs.orElse(null);
        return Optional.ofNullable(srsUrlObj)
                .map(it -> {
                    String url = it.getRtcPublishPullUrl();
                    String msgType = reqOffer.getMsgType();
                    OfferDTO.OfferDTOBuilder dtoBuilder = OfferDTO.builder()
                            .streamurl(url)
                            .clientip(reqOffer.getClientIp())
                            .sdp(reqOffer.getSdp());
                    AnswerDto dto;
                    if (ObjectUtil.equal(MsgTypeEnum.ReqSponsor.getCode(), msgType)) {
                        OfferDTO offerDTO = dtoBuilder.api(config.getUrl().concat(SrsHttpApi.PUBLISH)).build();
                        dto = srsApi.publish(offerDTO);
                    } else {
                        OfferDTO offerDTO = dtoBuilder.api(config.getUrl().concat(SrsHttpApi.PULL)).build();
                        dto = srsApi.pull(offerDTO);
                    }
                    return dto;
                }).map(it -> {
                    log.info("返回数据：answer 状态码为：{}", it.getCode());
                    //answerDto to RespAnswer
                    RespAnswer respAnswer = covertAnswer(it, srsUrlObj);
                    if (ObjectUtil.isNotNull(respAnswer.getSdp()) && ObjectUtil.isNotNull(respAnswer.getSessionId())) {
                        FutureAnswer build = FutureAnswer.builder().code(0).respAnswer(respAnswer).newsLetter(news).build();
                        return CompletableFuture.completedFuture(build);
                    }
                    return null;
                }).orElseGet(() -> {
                    FutureAnswer build = FutureAnswer.builder().code(-1).newsLetter(news).build();
                    return CompletableFuture.completedFuture(build);
                });
    }

    /**
     * 得到UrlSrs对象
     * @param newsLetter from
     * @param reqOffer reqOffer
     * @return SrsUrlObj
     */
    private Optional<SrsUrlObj> getSrsUrlObj(NewsLetter newsLetter, ReqOffer reqOffer) {
        String roomCode = reqOffer.getRoomCode();
        RoomFactoryHandleEvent.RoomFactoryHandleEventBuilder roomFactoryHandleEventBuilder = RoomFactoryHandleEvent.builder().newsLetter(newsLetter);
        if (ObjectUtil.equal(reqOffer.getMsgType(), MsgTypeEnum.ReqSponsor.getCode())) {
            roomFactoryHandleEventBuilder.isCreate(true);
        }
        RoomFactoryHandleEvent roomFactoryHandleEvent = roomFactoryHandleEventBuilder.roomEnum(RoomEnum.of(roomCode)).build();
        Room room = roomFactoryContext.todo(roomFactoryHandleEvent);
        if (room != null) {
            return room.getStreamUrlForUid(newsLetter.getFrom());
        }
        return Optional.empty();
    }

    /**
     * answerDto 转 RespAnswer
     *
     * @param answerDto answerDto
     * @param url       url
     * @return RespAnswer
     */
    private RespAnswer covertAnswer(AnswerDto answerDto, SrsUrlObj url) {
        return RespAnswer.builder().server(Objects.requireNonNull(answerDto).getServer())
                .sdp(answerDto.getSdp()).urlObj(url).sessionId(answerDto.getSessionid())
                .msgType(MsgTypeEnum.RespAnswer.getCode()).build();
    }
}
