<template>
  <div class="c-camera-detail">
    <div class="l-flex--row center c-camera-detail__header">
      <div class="c-camera-detail__name u-ellipsis"> {{ camera.name }}</div>
      <i
        class="c-camera-detail__close el-icon-close u-pointer"
        @click="close"
      />
    </div>
    <video
      ref="video"
      class="c-camera-detail__video o-simple-video"
      :poster="poster"
      autoplay
      muted
      @play="onVideoPlay"
      @pause="onVideoPause"
      @waiting="onVideoWaiting"
      @playing="onVideoPlaying"
      @error="onVideoError"
    />
    <div class="c-camera-detail__footer has-padding">
      <div class="l-flex--row c-sibling-item--v c-video-controls">
        <div
          v-if="settingsShow"
          class="settingB"
          @click.stop
        >
          <template v-if="settingTab">
            <div
              class="settingT settingsub"
              @click="onCloseSettingTab"
            >
              <i class="el-icon-arrow-left" />{{ settingActive.label }}
            </div>
            <div class="settingHeight">
              <div
                v-for="item in videoSettings[settingActive.value]"
                :key="item.value"
                class="settingT settingsub"
                @click="settingClick(item)"
              >
                <i :class="{ 'el-icon-check': item.active }" />
                {{ item.label }}
              </div>
            </div>
          </template>
          <template v-else>
            <div
              v-for="tab in tabs"
              :key="tab.value"
              class="settingT"
              @click="onClickSettings(tab)"
            >
              {{ tab.label }} <i class="el-icon-arrow-right" />
            </div>
          </template>
        </div>
        <div class="l-flex__auto">
          <i
            v-if="loading"
            class="c-video-controls__btn el-icon-loading"
          />
          <i
            v-else
            class="c-video-controls__btn has-active u-pointer"
            :class="iconClass"
            @click="onPlayOrPause"
          />
        </div>
        <i
          class="c-video-controls__btn settings el-icon-setting has-active u-pointer"
          @click.stop="onSettings"
        />
        <i
          class="c-video-controls__btn el-icon-refresh has-active u-pointer"
          @click="onRefresh"
        />
      </div>
      <div
        v-if="isTraffic"
        class="c-sibling-item--v far c-camera-detail__traffic has-padding"
      >
        <div
          id="main"
          class="o-canvas"
        />
        <div class="c-choose-date">
          <div class="c-sibling-item c-choose-date__type u-pointer">
            <span
              class="c-choose-date__item"
              :class="{ active: active === 'hour' }"
              @click="onTimeTypeChanged('hour')"
            >
              1小时
            </span>
            <span
              class="c-choose-date__item"
              :class="{ active: active === 'day' }"
              @click="onTimeTypeChanged('day')"
            >
              1天
            </span>
          </div>
          <el-date-picker
            v-model="dateValue"
            class="c-sibling-item far c-choose-date__date u-pointer"
            type="date"
            value-format="yyyy-MM-dd"
            :editable="false"
            :clearable="false"
            @change="getStatistic"
          />
          <el-time-select
            v-model="timeValue"
            class="c-sibling-item c-choose-date__time u-pointer"
            :picker-options="timePickerOptions"
            :editable="false"
            :clearable="false"
            @change="getStatistic"
          />
        </div>
      </div>
    </div>
  </div>
</template>

<script>
import { mapGetters } from 'vuex'
import * as echarts from 'echarts'
import {
  getStatistic,
  getVideoinfo,
  getAvailableParam,
  setCamera
} from '@/api/camera'
import {
  GATEWAY_CAMERA,
  Camera
} from '@/constant'
import { parseTime } from '@/utils'
import playerMixin from '../../player'

export default {
  name: 'CameraDetail',
  mixins: [playerMixin],
  props: {
    camera: {
      type: Object,
      required: true
    }
  },
  data () {
    const now = new Date()

    return {
      active: 'hour', // hour是小时，day是天
      settingActive: 'items',
      tabs: [
        { value: 'items', label: '分辨率' },
        { value: 'fps', label: '帧率' },
        { value: 'bitRates', label: '码率' }
      ],
      settingTab: true,
      settingsShow: false,
      videoSettings: null,
      infoData: null,
      dateValue: parseTime(now, '{y}-{m}-{d}'),
      timeValue: parseTime(now, '{h}:00'),
      timePickerOptions: {
        start: '00:00',
        step: '01:00',
        end: '23:00'
      }
    }
  },
  computed: {
    ...mapGetters(['token']),
    isTraffic () {
      return this.camera.cameraType === Camera.TRAFFIC
    },
    iconClass () {
      return this.paused || this.needReset ? 'el-icon-video-play' : 'el-icon-video-pause'
    }
  },
  created () {
    this.getAvailableParam()
  },
  mounted () {
    this.createPlayer()
    if (this.isTraffic) {
      this.getStatistic()
      window.addEventListener('resize', this.onResize)
    }
  },
  beforeDestroy () {
    if (this.isTraffic) {
      window.removeEventListener('resize', this.onResize)
    }
  },
  methods: {
    close () {
      this.destroyPlayer()
      this.$emit('close')
    },
    createPlayer () {
      this.playUrl(`${GATEWAY_CAMERA}/${this.camera.identifier}?authorization=${this.token}`)
    },
    setCamera () {
      this.hideSettingsMenu()
      setCamera({
        deviceId: this.camera.identifier,
        ...this.infoData
      }).then(
        () => {
          this.dataInit()
          this.destroyPlayer()
          this.createPlayer()
        },
        () => {
          this.infoData = { ...this.$infoData }
        }
      )
    },
    getAvailableParam () {
      if (this.$videoPramsLoading) {
        this.$message({
          type: 'warning',
          message: '配置获取中，请稍后重试'
        })
        return
      }
      this.$videoPramsLoading = true
      getAvailableParam().then(({ data }) => {
        this.videoSettings = {
          items: data.itemList.map(item => {
            // maxBitRateOptions: 20480
            // minBitRateOptions: 3
            // resolutionFpsMax: 20
            // snHight: 1944
            // snWidth: 2592
            return {
              value: `${item.snWidth}*${item.snHight}`,
              label: `${item.snWidth}*${item.snHight}`,
              active: false,
              ...item
            }
          }),
          fps: [],
          bitRates: [],
          streamRateType: data.streamRateTypeList
        }
        this.getVideoinfo()
      }).finally(() => {
        this.$videoPramsLoading = false
      })
    },
    onSettings () {
      if (!this.videoSettings) {
        this.getAvailableParam()
        return
      }
      if (!this.infoData) {
        this.getVideoinfo()
        return
      }
      this.settingTab = false
      if (this.settingsShow) {
        this.hideSettingsMenu()
      } else {
        document.addEventListener('click', this.hideSettingsMenu)
        this.settingsShow = true
      }
    },
    hideSettingsMenu () {
      if (this.settingsShow) {
        this.settingsShow = false
        document.addEventListener('click', this.hideSettingsMenu)
      }
    },
    onRefresh () {
      this.destroyPlayer()
      this.createPlayer()
    },
    onClickSettings (tab) {
      this.settingActive = tab
      this.settingTab = true
    },
    onCloseSettingTab () {
      this.settingTab = false
    },
    getVideoinfo () {
      if (this.$videoInfoLoading) {
        this.$message({
          type: 'warning',
          message: '配置获取中，请稍后重试'
        })
        return
      }
      this.$videoInfoLoading = true
      getVideoinfo(this.camera.identifier).then(({ data }) => {
        const { width, hight, frameRate, bitRate } = data
        this.infoData = { width, hight, frameRate, bitRate }
        this.dataInit()
      }).finally(() => {
        this.$videoInfoLoading = false
      })
    },
    dataInit () {
      const { width, hight, frameRate, bitRate } = this.infoData
      const value = `${width}*${hight}`
      let target = null

      this.videoSettings.items.forEach(item => {
        if (item.value === value) {
          item.active = true
          target = item
        } else {
          item.active = false
        }
      })

      if (target) {
        const fps = []
        const max = target.resolutionFpsMax
        for (let i = 1; i <= max; i++) {
          fps.push({ value: i, label: `${i}fps`, active: i === frameRate })
        }
        this.videoSettings.fps = fps

        const bitRates = []
        const minBitRate = target.minBitRateOptions
        const maxBitRate = target.maxBitRateOptions
        const streamRateType = this.videoSettings.streamRateType
        for (let i = 0; i < streamRateType.length; i++) {
          const rateType = streamRateType[i]
          if (rateType >= minBitRate && rateType <= maxBitRate) {
            bitRates.push({ value: rateType, label: `${rateType}kb/s`, active: rateType === bitRate })
          }
        }
        this.videoSettings.bitRates = bitRates
      } else {
        this.videoSettings.items = [
          { label: `${width}*${hight}`, active: true }
        ]
        this.videoSettings.fps = [
          { value: frameRate, label: `${frameRate}fps`, active: true }
        ]
        this.videoSettings.bitRates = [
          { value: bitRate, label: `${bitRate}kb/s`, active: true }
        ]
      }
    },
    settingClick (item) {
      let value = null
      switch (this.settingActive.value) {
        case 'items':
          value = `${this.infoData.width}*${this.infoData.hight}`
          break
        case 'fps':
          value = this.infoData.frameRate
          break
        case 'bitRates':
          value = this.infoData.bitRate
          break
        default:
          return
      }
      if (value === item.value) {
        return
      }
      this.$infoData = { ...this.infoData }
      switch (this.settingActive.value) {
        case 'items':
          this.infoData.width = item.snWidth
          this.infoData.hight = item.snHight
          this.infoData.frameRate = Math.min(item.resolutionFpsMax, this.infoData.frameRate)
          this.infoData.bitRate = Math.max(item.minBitRateOptions, Math.min(item.maxBitRateOptions, this.infoData.bitRate))
          break
        case 'fps':
          this.infoData.frameRate = item.value
          break
        case 'bitRates':
          this.infoData.bitRate = item.value
          break
        default:
          break
      }
      this.setCamera()
    },
    onTimeTypeChanged (type) {
      if (this.active === type) {
        return
      }
      this.active = type
      this.getStatistic()
    },
    getStatistic () {
      const endTime = `${this.dateValue} ${this.timeValue}:00`
      const date = new Date(endTime)
      switch (this.active) {
        case 'hour':
          date.setHours(date.getHours() - 1)
          break
        default:
          date.setDate(date.getDate() - 1)
          break
      }
      const startTime = parseTime(date, '{y}-{m}-{d} {h}:{i}:{s}')
      this.refreshEchart([])
      getStatistic({
        deviceId: this.camera.identifier,
        startTime,
        endTime,
        pageIndex: 1,
        pageSize: 10000
      }).then(({ data }) => {
        this.refreshEchart(data)
      })
    },
    getEchartData (data) {
      const date = new Date(`${this.dateValue} ${this.timeValue}:00`)
      const xdata = []
      const ydata = []
      if (this.active === 'hour') {
        date.setHours(date.getHours() - 1)
        for (let i = 0; i <= 60; i++) {
          const value = parseTime(date, '{y}-{m}-{d} {h}:{i}')
          xdata.push(value.split(' ')[1])
          ydata.push(data[value] || 0)
          date.setMinutes(date.getMinutes() + 1)
        }
      } else {
        date.setDate(date.getDate() - 1)
        for (let i = 0; i <= 24; i++) {
          const value = parseTime(date, '{y}-{m}-{d} {h}')
          xdata.push(`${value.split(' ')[1]}:00`)
          ydata.push(data[value] || 0)
          date.setHours(date.getHours() + 1)
        }
      }
      return { xdata, ydata }
    },
    transformEchartData (data) {
      const ydata = {}
      const isHour = this.active === 'hour'
      data.forEach(({ eventTime, insidePeopleNum }) => {
        const key = eventTime.slice(0, isHour ? 16 : 13)
        if (ydata[key]) {
          ydata[key] = Math.max(ydata[key], insidePeopleNum)
        } else {
          ydata[key] = insidePeopleNum
        }
      })
      return this.getEchartData(ydata)
    },
    onResize () {
      this.$echarts?.resize()
    },
    refreshEchart (echartsData) {
      const { xdata, ydata } = this.transformEchartData(echartsData)
      if (!this.$echarts) {
        this.$echarts = echarts.init(document.getElementById('main'))
      }
      this.$echarts?.setOption({
        title: {
          text: '区域内人数',
          textStyle: {
            color: '#fff',
            fontWeight: 'bold'
          }
        },
        xAxis: {
          type: 'category',
          data: xdata,
          axisLine: {
            lineStyle: {
              color: '#4779BC'
            }
          },
          axisLabel: {
            color: '#A9CEFF'
          }
        },
        yAxis: {
          type: 'value',
          minInterval: 1,
          splitLine: {
            lineStyle: {
              color: '#4779BC',
              type: 'dashed'
            }
          },
          axisLine: {
            lineStyle: {
              color: '#4779BC'
            }
          },
          axisLabel: {
            color: '#A9CEFF'
          }
        },
        grid: {
          left: '30',
          right: '20',
          top: '40',
          bottom: '20'
        },
        series: [
          {
            data: ydata,
            type: 'bar',
            showBackground: true,
            backgroundStyle: {
              color: 'transparent'
            },
            itemStyle: {
              color: 'rgba(0, 191, 208, 0.5)'
            },
            select: {
              itemStyle: {
                color: 'rgb(0, 234, 255)'
              }
            }
          }
        ],
        tooltip: {
          formatter: '时间：{b}<br />人流量：{c}'
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
$theme-blue: #003e90;

.c-camera-detail {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;

  &__video {
    width: 100%;
    height: 100%;
  }

  &__header {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 42px;
    color: #fff;
    font-size: 24px;
    text-align: center;
    background-color: rgba($theme-blue, 0.8);
    z-index: 9;

    &::after {
      content: "";
      position: absolute;
      top: 100%;
      left: 50%;
      width: 700px;
      height: 0;
      border-top: 16px solid rgba($theme-blue, 0.8);
      border-right: 16px solid transparent;
      border-bottom: 16px solid transparent;
      border-left: 16px solid transparent;
      transform: translateX(-50%);
    }
  }

  &__name {
    display: inline-block;
    width: 600px;
  }

  &__close {
    position: absolute;
    top: 50%;
    right: 0;
    padding: $spacing;
    color: #fff;
    font-size: 32px;
    transform: translateY(-50%);
  }

  &__footer {
    position: absolute;
    left: 0;
    bottom: 0;
    width: 100%;
  }

  &__traffic {
    position: relative;
    line-height: 1;
    border-radius: $radius--mini;
    background-color: rgba($theme-blue, 0.8);
  }
}

.c-video-controls {
  position: relative;
  height: 48px;
  padding: 0 32px 0 16px;
  border-radius: $radius--mini;
  background-color: rgba(#00060d, 0.75);

  &__btn {
    color: #fff;
    font-size: 32px;

    &.settings {
      margin-right: 32px;
    }
  }
}

.settingB {
  position: absolute;
  right: 134px;
  bottom: 48px;
  padding: 10px 0px;
  color: #fff;
  background-color: rgba(#000, 0.85);
  transform: translateX(50%);

  .settingT {
    position: relative;
    padding: 0px 16px;
    width: 180px;
    height: 40px;
    line-height: 40px;
    cursor: pointer;

    &:hover {
      background-color: rgba(#454545, 0.85);
    }

    i {
      position: absolute;
      top: 13px;
      right: 16px;
    }
  }

  .settingHeight {
    max-height: 250px;
    overflow: auto;
  }

  .settingsub {
    width: 140px;
    padding-left: 42px;

    i {
      position: absolute;
      left: 16px;
    }
  }
}

.c-choose-date {
  position: absolute;
  right: $spacing;
  top: $spacing;
  color: #fff;

  &__type {
    display: inline-block;
    height: 24px;
    line-height: 24px;
    border-radius: $radius--mini;
    background-color: #4478bc;
  }

  &__item {
    display: inline-block;
    width: 50px;
    font-size: 14px;
    text-align: center;
    border-radius: $radius--mini;
    background-color: #4478bc;

    &.active {
      background: #0096ff;
    }
  }

  &__date {
    width: 130px;
  }

  &__time {
    width: 80px;
  }

  ::v-deep input {
    height: 24px;
    padding-right: 10px;
    color: #fff;
    font-size: 14px;
    line-height: 24px;
    background-color: transparent;
  }

  ::v-deep .el-input__icon {
    line-height: 24px;
  }
}

.o-canvas {
  width: 100%;
  height: 200px;
}
</style>
