<template>
  <div style="width: 100%">
    <div class="page-header">
      <div class="page-title">
        <el-page-header @back="goBack" :content="$t('menu.record')"></el-page-header>
      </div>
    </div>
    <el-container>
      <el-aside width="300px">
        <div class="record-list-box-box">
<!--          -->
          <el-date-picker size="mini" v-model="chooseDate" type="date" value-format="yyyy-MM-dd" :placeholder="$t('date')"
                          @change="dateChange()"></el-date-picker>
<!--          格式选择 与日期选择框样式对其-->
          <el-select style="width: 220px" v-model="filterExt" size="mini" @change="filterExtChangeHandle" :placeholder="$t('filter')">
            <el-option
                v-for="item in extList"
                :key="item.value"
                :label="item.label"
                :value="item.value"
            >
            </el-option>
          </el-select>
          <div class="record-list-box" v-loading="recordsLoading" :style="recordListStyle">
            <ul v-if="detailFiles.length >0" class="infinite-list record-list">
              <li v-for="item in detailFiles" class="infinite-list-item record-list-item">

                <el-tag @click="checkedFile(item)" :type="chooseFile == item?'danger':''">
                  <i class="el-icon-video-camera"></i>
                  <span class="icon" :class="'icon-'+item.extName">{{item.extName}}</span>
                  {{ moment(item.startTime).format('HH:mm:ss') }}-{{ moment(item.endTime).format('HH:mm:ss') }}
                </el-tag>
                <i style="color: #409EFF;margin-left: 5px;" class="el-icon-download" @click="downloadRecord(item)"></i>
              </li>
            </ul>
          </div>
          <div size="mini" v-if="detailFiles.length ==0" class="record-list-no-val">{{ $t('noData') }}</div>
        </div>

      </el-aside>
      <el-main style="padding-bottom: 10px;">
        <div class="playBox" :style="playerStyle">
          <player ref="recordVideoPlayer"
                  :videoUrl="videoUrl"
                  :error="videoError"
                  :message="videoError"
                  :hasAudio="hasAudio"
                  style="max-height: 100%"
                  v-if="activePlayer === 'jessibuca'"
                  fluent autoplay live></player>
          <rtc-player
              v-if="activePlayer === 'webrtc'"
              ref="webrtc"
              @eventCallback="webrtcPlayEventHandle"
              :videoUrl="videoUrl"
              :error="videoError"
              :message="videoError"
              :hasAudio="hasAudio"
          />
        </div>
        <div class="player-option-box">
          <div>
            <el-radio-group
                v-model="activePlayer"
                size="medium"
                @input="playerChangeHandle"
            >
              <el-radio-button
                  v-for="(item,i) in playerList"
                  :key="item.key + i"
                  :label="$t(`video.play.${item.key}.title`)">
                {{ $t(`video.play.${item.key}.title`) }}
              </el-radio-button>
            </el-radio-group>

            <el-button-group>
              <el-time-picker
                  size="mini"
                  is-range
                  align="left"
                  v-model="timeRange"
                  value-format="yyyy-MM-dd HH:mm:ss"
                  range-separator="-"
                  :start-placeholder="$t('video.startTime')"
                  :end-placeholder="$t('video.endTime')"
                  @change="timePickerChange"
                  :placeholder="$t('video.timeRange')">
              </el-time-picker>
            </el-button-group>

            <el-button-group>
              <el-button size="mini" class="iconfont icon-zanting"
                         :title="$t('play')"
                         @click="gbPause()"></el-button>
              <el-button size="mini" class="iconfont icon-kaishi"
                         :title="$t('pause')"
                         @click="gbPlay()"></el-button>
              <el-dropdown size="mini" :title="$t('playMultiples')" @command="gbScale">
                <el-button size="mini">
                  {{ $t('playMultiples') }} <i class="el-icon-arrow-down el-icon--right"></i>
                </el-button>
                <el-dropdown-menu slot="dropdown">
                  <el-dropdown-item command="0.25">0.25</el-dropdown-item>
                  <el-dropdown-item command="0.5">0.5</el-dropdown-item>
                  <el-dropdown-item command="1.0">1</el-dropdown-item>
                  <el-dropdown-item command="2.0">2</el-dropdown-item>
                  <el-dropdown-item command="4.0">4</el-dropdown-item>
                </el-dropdown-menu>
              </el-dropdown>
              <el-button size="mini" class="iconfont icon-xiazai1" :title="$t('download')"
                         @click="downloadRecord()"></el-button>
            </el-button-group>
          </div>
          <el-slider
              class="playtime-slider"
              v-model="playTime"
              id="playtimeSlider"
              :disabled="detailFiles.length === 0"
              :min="sliderMIn"
              :max="sliderMax"
              :range="true"
              :format-tooltip="playTimeFormat"
              @change="playTimeChange"
              :marks="playTimeSliderMarks">
          </el-slider>
          <div class="slider-val-box">
            <div class="slider-val" v-for="item of detailFiles"
                 :style="'width:' + getDataWidth(item) + '%; left:' + getDataLeft(item) + '%'"></div>
          </div>
        </div>

      </el-main>
    </el-container>
    <recordDownload ref="recordDownload"></recordDownload>
  </div>
</template>


<script>
import uiHeader from '../layout/UiHeader.vue'
import player from './common/jessibuca.vue'
import moment from 'moment'
import recordDownload from './dialog/recordDownload.vue'
import handle from "@/until/handle";
import RtcPlayer from "@components/dialog/rtcPlayer.vue";
import mpegTsVideo from "@components/common/mpegtsVideo.vue";
import h265WebJessibuca from "@components/common/h265webJessibuca.vue";
import H265WebJs from "@components/common/h265webJs.vue";
import {webrtcEvent} from "@/map/eventMap";
import {strFill} from "@/until/str";
import {checkWebrtcHevcSupport} from "../until/browser";

const playList = [
  {
    key: "webrtc",
    text: "webrtc 播放器",
    description: "延迟较低的播放器,需要浏览器支持",
    support: checkWebrtcHevcSupport()? ['h264', 'h265'] : ['h264'],
    audioSupport: ['opus', 'pcma', 'pcmu'],
    disable: false
  },
  {
    key: "jessibuca",
    text: "265 jessibuca播放器",
    description: "用于播放265格式视频",
    support: ['h264', 'h265'],
    audioSupport: ['aac'],
    disable: false
  },
];
const playerProtocol = {
  webrtc: ["rtc", "rtcs"],
  jessibuca: ["ws_flv", "wss_flv"],
};
let playTimeSliderMarks = {};
for (let i = 0 ; i < 24 ; i++)
{
  playTimeSliderMarks[i * 3600] = `${strFill(i, 2)}:00`;
}

export default {
  name: 'app',
  components: {
    H265WebJs, h265WebJessibuca, mpegTsVideo,
    RtcPlayer,
    uiHeader, player, recordDownload
  },
  data() {
    return {
      activePlayer: '',
      playerList: playList,
      fps: 15,
      deviceId: this.$route.params.deviceId,
      channelId: this.$route.params.channelId,
      recordsLoading: false,
      streamId: "",
      hasAudio: true,
      allDetailFiles: [],
      // detailFiles: [],
      chooseDate: null,
      videoUrl: null,
      chooseFile: null,
      streamInfo: null,
      app: null,
      mediaServerId: null,
      ssrc: null,
      sliderMIn: 0,
      sliderMax: 86400,
      autoPlay: true,
      taskUpdate: null,
      tabVal: "running",
      recordListStyle: {
        height: this.winHeight + "px",
        overflow: "auto",
        margin: "10px auto 10px auto"
      },
      playerStyle: {
        "margin": "0 auto 20px auto",
        "height": this.winHeight + "px",
      },
      winHeight: window.innerHeight - 240,
      playTime: null,
      timeRange: null,
      startTime: null,
      endTime: null,
      playTimeSliderMarks: playTimeSliderMarks,
      extList: [],
      filterExt: null,
    };
  },
  computed: {
    detailFiles() {
      let ext = this.filterExt;
      if(!ext){
        return this.allDetailFiles;
      }
      if(ext === 'all') {
        return this.allDetailFiles;
      }
      return this.allDetailFiles.filter((item) => {
        return item.extName === ext;
      })
    }
  },
  mounted() {
    this.recordListStyle.height = this.winHeight + "px";
    this.playerStyle["height"] = this.winHeight + "px";
    this.chooseDate = moment().format('YYYY-MM-DD')
    this.dateChange();
    if(!this.activePlayer){
      this.activePlayer = this.playerList[0].key;
    }
  },
  beforeDestroy() {
    console.log('准备销毁页面')
    this.stopPlayRecord();
    this.stopDownloadRecord();
  },
  destroyed() {
    this.$destroy('recordVideoPlayer');
  },
  methods: {
    async dateChange() {
      let err, res;
      let recordList = [];
      if (!this.chooseDate) {
        return;
      }

      this.setTime(this.chooseDate + " 00:00:00", this.chooseDate + " 23:59:59");
      this.recordsLoading = true;
      // this.detailFiles = [];
      let url = '/api/gb_record/query/'
      url += `${this.deviceId}/${this.channelId}`;
      url += `?startTime=${this.startTime}`;
      url += `&endTime=${this.endTime}`;
      [err, res] = await handle(this.$axios.axios({
        method: 'get',
        url: url
      }))
      this.recordsLoading = false;
      if (err) {
        this.$message({
          showClose: true,
          message: err.message,
          type: "error",
        });
        return;
      }
      if (res.data.code !== 0) {
        this.$message({
          showClose: true,
          message: res.data.msg,
          type: "error",
        });
      }
      // 创建一个set集合
      let extSet = new Set();
      recordList = res.data.data.recordList;
      // 遍历获取文件后缀名
      recordList.forEach((item) => {
        // item.name = item.fileName;
        item.extName = this.getExtName(item.name);
        extSet.add(item.extName);
      })
      this.allDetailFiles = recordList;
      // 将set集合转换为数组

      this.extList = Array.from(extSet).map((item) => {
        return {
          label: item,
          value: item
        }
      });
      // 首位添加 所有格式
      this.extList.unshift({
        label: "all",
        value: "all"
      });
      this.filterExt = "all";
      console.log(this.detailFiles);
    },
    getExtName(fileName){
      let tmpSplit = fileName.split(".");
      let extName = tmpSplit[tmpSplit.length - 1];
      return extName;
    },
    moment: function (v) {
      return moment(v)
    },
    setTime: function (startTime, endTime) {
      this.startTime = startTime;
      this.endTime = endTime;
      let start = (new Date(this.startTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime()) / 1000;
      let end = (new Date(this.endTime).getTime() - new Date(this.chooseDate + " 00:00:00").getTime()) / 1000;
      console.log(start)
      console.log(end)
      this.playTime = [start, end];
      this.timeRange = [startTime, endTime];
    },
    videoError: function (e) {
      console.log("播放器错误：" + JSON.stringify(e));
    },
    checkedFile(file) {
      this.chooseFile = file;
      this.setTime(file.startTime, file.endTime);
      // 开始回放
      this.playRecord()
    },
    playRecord: function () {
      if (this.streamId !== "") {
        this.stopPlayRecord(() => {
          this.streamId = "";
          this.playRecord();
        })
      } else {
        this.$axios.axios({
          method: 'get',
          url: '/api/playback/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + this.startTime + '&endTime=' +
              this.endTime
        }).then(async (res) => {
          if (res.data.code === 0) {
            this.streamInfo = res.data.data;
            await this.queryMediaInfo(true);
            console.log(`streamInfo`);
            console.log(this.streamInfo);
            this.app = this.streamInfo.app;
            this.streamId = this.streamInfo.stream;
            this.mediaServerId = this.streamInfo.mediaServerId;
            this.ssrc = this.streamInfo.ssrc;
            // 根据tracks 选择播放器

            this.videoUrl = this.getUrlByStreamInfo(this.streamInfo);
          } else {
            this.$message({
              showClose: true,
              message: res.data.msg,
              type: "error",
            });
          }
        });
      }
    },
    gbPlay() {
      console.log('前端控制：播放');
      this.$axios.axios({
        method: 'get',
        url: '/api/playback/resume/' + this.streamId
      }).then((res) => {
        this.$refs["recordVideoPlayer"].play(this.videoUrl)
      });
    },
    gbPause() {
      console.log('前端控制：暂停');
      this.$axios.axios({
        method: 'get',
        url: '/api/playback/pause/' + this.streamId
      }).then(function (res) {
      });
    },
    gbScale(command) {
      console.log('前端控制：倍速 ' + command);
      this.$axios.axios({
        method: 'get',
        url: `/api/playback/speed/${this.streamId}/${command}`
      }).then(function (res) {
      });
    },
    downloadRecord: function (row) {
      if (!row) {
        let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[0] * 1000).format("YYYY-MM-DD HH:mm:ss");
        let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + this.playTime[1] * 1000).format("YYYY-MM-DD HH:mm:ss");
        console.log(startTimeStr);
        console.log(endTimeStr);
        row = {
          startTime: startTimeStr,
          endTime: endTimeStr
        }
      }
      if (this.streamId !== "") {
        this.stopPlayRecord(() => {
          this.streamId = "";
          this.downloadRecord(row);
        })
      } else {
        this.$axios.axios({
          method: 'get',
          url: '/api/gb_record/download/start/' + this.deviceId + '/' + this.channelId + '?startTime=' + row.startTime + '&endTime=' +
              row.endTime + '&downloadSpeed=4'
        }).then((res) => {
          if (res.data.code === 0) {
            let streamInfo = res.data.data;
            this.$refs.recordDownload.openDialog(this.deviceId, this.channelId, streamInfo.app, streamInfo.stream, streamInfo.mediaServerId);
          } else {
            this.$message({
              showClose: true,
              message: res.data.msg,
              type: "error",
            });
          }
        });
      }
    },
    stopDownloadRecord: function (callback) {
      this.$refs["recordVideoPlayer"].pause();
      this.videoUrl = '';
      this.$axios.axios({
        method: 'get',
        url: '/api/gb_record/download/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
      }).then((res) => {
        if (callback) callback(res)
      });
    },
    stopPlayRecord: function (callback) {
      this.$refs["recordVideoPlayer"].pause();
      this.videoUrl = '';
      this.$axios.axios({
        method: 'get',
        url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
      }).then(function (res) {
        if (callback) callback()
      });
    },
    getDataWidth(item) {
      let timeForFile = this.getTimeForFile(item);
      let result = (timeForFile[2]) / ((this.sliderMax - this.sliderMIn) * 1000)
      return result * 100
    },
    getDataLeft(item) {
      let timeForFile = this.getTimeForFile(item);
      let differenceTime = timeForFile[0].getTime() - new Date(this.chooseDate + " 00:00:00").getTime()
      return parseFloat((differenceTime - this.sliderMIn * 1000) / ((this.sliderMax - this.sliderMIn) * 1000)) * 100;
    },
    getUrlByStreamInfo(streamInfo) {
      if (this.enableDebug) {
        console.log("获取基础拉流地址");
        console.log(streamInfo);
      }
      if (!streamInfo) {
        return '';
      }
      if(!this.activePlayer){
        this.activePlayer = this.playerList[0].key;
      }
      let playerData = playerProtocol[this.activePlayer];
      if (location.protocol === "https:") {
        this.videoUrl = streamInfo[playerData[1]]
      } else {
        this.videoUrl = streamInfo[playerData[0]]
      }
      if (this.enableDebug) {
        console.log(`播放url: ${this.videoUrl}`);
      }
      console.log(`播放url: ${this.videoUrl}`);
      console.log(this.videoUrl)

      return this.videoUrl;
    },
    timePickerChange: function (val) {
      this.setTime(val[0], val[1])
    },
    playTimeChange(val) {
      console.log(val)

      let startTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[0] * 1000).format("YYYY-MM-DD HH:mm:ss");
      let endTimeStr = moment(new Date(this.chooseDate + " 00:00:00").getTime() + val[1] * 1000).format("YYYY-MM-DD HH:mm:ss");

      this.setTime(startTimeStr, endTimeStr)

      this.playRecord();
    },
    setSliderFit() {
      if (this.sliderMIn === 0 && this.sliderMax === 86400) {
        if (this.detailFiles.length > 0) {
          let timeForFile = this.getTimeForFile(this.detailFiles[0]);
          let lastTimeForFile = this.getTimeForFile(this.detailFiles[this.detailFiles.length - 1]);
          let timeNum = timeForFile[0].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()
          let lastTimeNum = lastTimeForFile[1].getTime() - new Date(this.chooseDate + " " + "00:00:00").getTime()

          this.playTime = parseInt(timeNum / 1000)
          this.sliderMIn = parseInt(timeNum / 1000 - timeNum / 1000 % (60 * 60))
          this.sliderMax = parseInt(lastTimeNum / 1000 - lastTimeNum / 1000 % (60 * 60)) + 60 * 60

          this.playTime = [this.sliderMIn, this.sliderMax];
        }
      } else {
        this.sliderMIn = 0;
        this.sliderMax = 86400;
      }
    },
    getTimeForFile(file) {
      let startTime = new Date(file.startTime);
      let endTime = new Date(file.endTime);
      return [startTime, endTime, endTime.getTime() - startTime.getTime()];
    },
    playTimeFormat(val) {
      let h = parseInt(val / 3600);
      let m = parseInt((val - h * 3600) / 60);
      let s = parseInt(val - h * 3600 - m * 60);

      let hStr = h;
      let mStr = m;
      let sStr = s;
      if (h < 10) {
        hStr = "0" + hStr;
      }
      if (m < 10) {
        mStr = "0" + mStr;
        s
      }
      if (s < 10) {
        sStr = "0" + sStr;
      }
      return hStr + ":" + mStr + ":" + sStr
    },
    goBack() {
      window.history.go(-1);
    },
    filterExtChangeHandle(){
      let ext = this.filterExt;
      if(!ext){
        return
      }
      if(ext === 'all') {
        this.detailFiles = this.detailFiles;
      }

    },
    findPlayer(videoType, audioType)
    {
      // 先尝试寻找到所有支持对应协议的播放器
      let arr = this.playerList.filter(item => {
        return item.support.includes(videoType)
      })
      console.log(arr);
      console.log(arr);
      console.log(arr);
      console.log(arr);
      // 从中找到同时支持
      let res_player = arr.find(item => {
        // 判断播放器是否同时支持 视频与音频
        return item.audioSupport.includes(audioType);
      })
      if (!res_player)
      {
        res_player = arr[0]
      }

      return res_player;
    },
    async queryMediaInfo(isFirst) {
      let info = this.streamInfo
      let url = `/zlm/${info.mediaServerId}/index/api/getMediaInfo`
      url += `?vhost=__defaultVhost__`
      url += `&schema=rtsp`
      url += `&app=${info.app}`
      url += `&stream=${info.stream}`
      url += this.shareCode ? `&shareCode=${this.shareCode}` : ''
      let [err, res] = await handle(this.$axios.axios({
        method: 'get',
        url: url
      }));

      if (err) {
        console.error(err);
        this.$message.warning("流媒体信息获取失败")
        return;
      }
      console.log(res);
      if (res.data.code !== 0) {
        this.tracksNotLoaded = true;
        this.$message({
          showClose: true,
          message: '获取编码信息失败,',
          type: 'warning'
        });
        return;
      }
      if (res.data.tracks) {
        this.tracks = res.data.tracks;
        if (this.tracks) {
          console.log(`---------tracks----------`)
          // 根据我们摄像头默认fps值来进行配置播放器
          let fps = 15;
          let isH265 = false;
          let isPCMAudio = false;
          for (const tracksElement of this.tracks) {
            console.log(tracksElement);
            if (tracksElement.fps) {
              fps = tracksElement.fps;
            }

            console.log(`${tracksElement.codec_id_name}:code ${tracksElement.codec_id_name ? 'is h265' : 'not h265'}`)
            if (tracksElement.codec_id_name && tracksElement.codec_id_name.includes("265")) {
              isH265 = true;
            }

            if (tracksElement.codec_id_name && tracksElement.codec_id_name.includes("PCM"))
            {
              isPCMAudio = true;
              // console.log("audio")
            }
          }
          this.fps = fps;
          if (isFirst) {
            // g711 264
            // g711 265
            let _Player = this.findPlayer(isH265?'h265':'h264',
                isPCMAudio?'pcma':'aac');
            if (_Player) {
              console.log(`切换为${_Player.key}播放器`);
              this.activePlayer = _Player.key;
            } else {
              console.log("使用默认播放器");
              this.activePlayer = playList[0].key;
            }
          }
        }
      } else {
        console.log('没有编码信息');
      }
    },
    playerChangeHandle() {
      console.log('切换播放器');
      this.$nextTick(() => {
        // todo 切换url
        this.videoUrl = this.getUrlByStreamInfo(this.streamInfo);
      })
    },
    webrtcPlayEventHandle(type, e) {
      // 添加同类型防抖
      if (this.enableDebug) {
        console.log('playEventHandle');
        console.log(type, e);
      }
      if (this.playEventHandleTimer) {
        clearTimeout(this.playEventHandleTimer);
      }
      this.playEventHandleTimer = setTimeout(() => {
        this.webrtcEventExecute(type, e);
      }, 300);
    },
    webrtcEventExecute(type, e) {
      // 防抖,防止多次触发
      if (type === webrtcEvent.apiFail.code) {
        this.$notify.error({
          title: this.$t('notification.noStreamInfo'),
          dangerouslyUseHTMLString: true,
          message: this.$t('notification.zlmFailMsg',  {msg: e.message, url: this.videoUrl}),
          duration: 0
        });
        this.videoError = true;
        this.videoUrl = '';

      } else if (type === webrtcEvent.played.code) {
        this.$message.success(this.$t('notification.playSuccess'));
      } else if (type === webrtcEvent.sdpFail.code) {
        console.log(e);
        this.$notify.error({
          title: this.$t('notification.sdpFail'),
          duration: 14500
        })
      }
    },
  }
};
</script>
<style scoped>
.icon{
  font-size: 12px;
  margin-right: 5px;
}
.icon-mp4{
  color: #25cb8e;
}
.icon-h265{
  color: #ef7b05;
}
.icon-h264{
  color: #407300;
}
</style>
<style>
.el-slider__runway {
  background-color: rgba(206, 206, 206, 0.47) !important;
}

.el-slider__bar {
  background-color: rgba(153, 153, 153, 0) !important;
}

.playtime-slider {
  position: relative;
  z-index: 100;
}

.data-picker-true {

}

.data-picker-true:after {
  content: "";
  position: absolute;
  width: 4px;
  height: 4px;
  background-color: #606060;
  border-radius: 4px;
  left: 45%;
  top: 74%;

}

.data-picker-false {

}

.slider-val-box {
  height: 6px;
  position: relative;
  top: -22px;
}

.slider-val {
  height: 6px;
  background-color: #007CFF;
  position: absolute;
}

.record-list-box-box {
  width: 250px;
  float: left;
}

.record-list-box {
  overflow: auto;
  width: 220px;
  list-style: none;
  padding: 0;
  margin: 0;
  margin-top: 0px;
  padding: 1rem 0;
  background-color: #FFF;
  margin-top: 10px;
}

.record-list {
  list-style: none;
  padding: 0;
  margin: 0;
  background-color: #FFF;

}

.record-list-no-val {
  position: absolute;
  color: #9f9f9f;
  top: 50%;
  left: 110px;
}

.record-list-item {
  padding: 0;
  margin: 0;
  margin: 0.5rem 0;
  cursor: pointer;
}

.record-list-option {
  width: 10px;
  float: left;
  margin-top: 39px;

}

.player-option-box {
  padding: 0 20px;
}
</style>
