package com.inspect.ivs.controller;

import com.alibaba.fastjson.JSONObject;
import com.inspect.base.core.domain.Response;
import com.inspect.base.core.utils.StringUtils;
import com.inspect.base.redis.service.RedisService;
import com.inspect.ivs.constant.IvsConst;
import com.inspect.ivs.domain.CameraCodeAndEndTime;
import com.inspect.ivs.enums.RtspType;
import com.inspect.ivs.service.IvsCommonService;
import com.inspect.ivs.service.PlaybackComponent;
import com.inspect.ivs.service.XinTongComponent;
import com.inspect.ivs.service.ZlMediaComponent;
import com.inspect.ivs.util.TimeUtils;
import com.inspect.ivs.util.UriUtils;
import com.inspect.ivs.view.IvsRecListView;
import com.inspect.ivs.view.IvsVideoRtspView;
import com.inspect.ivs.view.IvsPlaybackStartView;
import com.inspect.ivs.view.IvsDevRecListView;
import com.inspect.ivs.vo.IvsPlaybackRec2ListVo;
import com.inspect.ivs.vo.IvsVideoRtspVo;
import com.inspect.ivs.vo.IvsPlaybackRecListVo;
import com.inspect.ivs.vo.IvsRecCtrlVo;
import com.inspect.ivs.vo.IvsStartRecVo;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.reactive.function.client.WebClient.RequestBodySpec;

@RestController
@RequestMapping({"/api/v1/playback"})
public class IvsPlaybackController {
    private static final Logger log = LoggerFactory.getLogger(IvsPlaybackController.class);
    private final IvsCommonService ivsCommonService;
    private final ZlMediaComponent zlmediaComponent;
    private final RedisService redisService;
    private final PlaybackComponent playbackComponent;
    @Value("${rtsp.type:xintong}")
    private RtspType rtspType;
    private final XinTongComponent xinTongComponent;

    public IvsPlaybackController(IvsCommonService ivsCommonService, ZlMediaComponent zlmediaComponent, RedisService redisService, PlaybackComponent playbackComponent, XinTongComponent xinTongComponent) {
        this.ivsCommonService = ivsCommonService;
        this.zlmediaComponent = zlmediaComponent;
        this.redisService = redisService;
        this.playbackComponent = playbackComponent;
        this.xinTongComponent = xinTongComponent;
    }

    @GetMapping({"recordlist"})
    public IvsDevRecListView recordList(IvsPlaybackRecListVo ivsPlaybackRecListVo) {
        log.debug("[PLAYBACK] playback-recordList ivsPlaybackRecordListVo:{}", ivsPlaybackRecListVo);
        IvsPlaybackRec2ListVo ivsPlaybackRec2ListVo = new IvsPlaybackRec2ListVo(ivsPlaybackRecListVo.getCode(), ivsPlaybackRecListVo.getStarttime(), ivsPlaybackRecListVo.getEndtime());
        IvsRecListView ivsRecListView = this.ivsCommonService.get(getLabel(), UriUtils.parse(IvsConst.URI_RECORD_LIST, ivsPlaybackRec2ListVo), IvsRecListView.class);
        log.debug("[PLAYBACK] playback-recordList ivsRecordListView:{}", ivsRecListView);
        log.debug("[PLAYBACK] playback recordList end");
        Map<String, CameraCodeAndEndTime> map = new HashMap<>();
        List<IvsRecListView.RecordInfo> recordInfos = ivsRecListView.getRecordInfos().getRecordInfoList().getRecordInfo();
        recordInfos.forEach((item) -> {
            map.put(item.getRecordFileName(), new CameraCodeAndEndTime(ivsPlaybackRecListVo.getCode(), TimeUtils.toSip(item.getRecordTime().getEndTime())));
        });
        this.redisService.setCacheMapValue(IvsConst.IVS_PLAYBACK_LIST, ivsPlaybackRecListVo.getCode(), map);
        return new IvsDevRecListView(ivsPlaybackRecListVo, ivsRecListView);
    }

    @GetMapping({"start"})
    public IvsPlaybackStartView start(IvsStartRecVo ivsStartRecVo) {
        log.debug("[PLAYBACK] playback start ivsStartRecordVo:{}", ivsStartRecVo);
        Map<String, CameraCodeAndEndTime> map = redisService.getCacheMapValue(IvsConst.IVS_PLAYBACK_LIST, ivsStartRecVo.getCameraId());
        CameraCodeAndEndTime cameraCodeAndEndTime = map.get(ivsStartRecVo.getRecordFileName());
        ivsStartRecVo.setCameraId(cameraCodeAndEndTime.getCameraCode());
        ivsStartRecVo.setEndTime(cameraCodeAndEndTime.getEndTime());
        String streamId = System.currentTimeMillis() + "";
        IvsVideoRtspView ivsVideoRtspView;
        switch (this.rtspType.ordinal()) {
            case 1:
                IvsVideoRtspVo ivsVideoRtspVo = IvsVideoRtspVo.playbackStream(ivsStartRecVo);
                log.info("[PLAYBACK] json: {}", JSONObject.toJSON(ivsVideoRtspVo));
                ivsVideoRtspView = ivsCommonService.postJson(getLabel(), ivsVideoRtspVo, IvsConst.URI_VIDEO_RTSP, IvsVideoRtspView.class);
                this.xinTongComponent.convert(ivsVideoRtspView.getRtspURL(), streamId, ivsVideoRtspView);
                break;
            default:
                ivsVideoRtspView = playbackComponent.postJson(getLabel(), ivsStartRecVo, IvsConst.URI_PLAYBACK_FLV, IvsVideoRtspView.class);
        }

        IvsPlaybackStartView ivsPlaybackStartView = new IvsPlaybackStartView(streamId, ivsVideoRtspView);
        log.debug("[PLAYBACK] playback start ivsStreamStartView:{}", ivsPlaybackStartView);
        log.debug("[PLAYBACK] playback start end");
        return ivsPlaybackStartView;
    }

    @GetMapping({"stop"})
    public Response stop(String streamId) {
        log.debug("==================playback-stop-streamId:{}", streamId);
        this.ivsCommonService.get(getLabel(), UriUtils.parse(IvsConst.URI_PLAYBACK_STOP, (new JSONObject()).fluentPut("handle", streamId)));
        log.debug("==================playback-stop-end");
        return Response.ok();
    }

    @GetMapping({"control"})
    public Response control(IvsRecCtrlVo ivsRecCtrlVo) {
        log.debug("[PLAYBACK] playback control ivsRecordControlVo:{}", ivsRecCtrlVo);
        String cookie = this.ivsCommonService.getCookie();
        this.ivsCommonService.http(ivsRecCtrlVo.getHttpMethod(), UriUtils.parse(ivsRecCtrlVo.getUrl(), ivsRecCtrlVo)).contentType(MediaType.APPLICATION_FORM_URLENCODED).cookie(IvsConst.COOKIE_SESSION_NAME, cookie).retrieve().bodyToMono(String.class).block();
        log.debug("[PLAYBACK] playback control end");
        return Response.ok();
    }

    public String getLabel() {
        return UUID.randomUUID().toString().trim().replaceAll(StringUtils.DASH, StringUtils.EMPTY);
    }
}
