<script lang="jsx">
import { getAcceptType } from '@/utils'
import { fileConverApi } from '@/api/system/resource'

import { dataReportMixin } from '@/utils/data-report'

function image (h) {
  return (
    <div class="r_t_image">
      <img
        src={this.src}
        draggable="false"
        style={`transform:translate(${this.image.x}px, ${this.image.y}px) scale(${this.image.s}) rotate(${this.image.r}deg)`}
        onmousedown={this.onMove}
      />
      <div class="actions">
        <i class="el-icon-zoom-in" onclick={() => this.imageScale(1)} />
        <i class="el-icon-refresh-right" onclick={() => this.imageRotate(1)} />
        <i class="el-icon-full-screen" onclick={() => this.onFullScreen()} />
        <i class="el-icon-refresh-left" onclick={() => this.imageRotate(-1)} />
        <i class="el-icon-zoom-out" onclick={() => this.imageScale(-1)} />
      </div>
    </div>
  )
}

function video (h) {
  return (
    <div class="r_t_mp4">
      <video
        src={this.src}
        controls
        disablePictureInPicture
        controlsList="nodownload noremoteplayback noplaybackrate"
        class={{ r_t_mp4: 1, timeline: this.timeline }}
      />
    </div>
  )
}

function audio (h) {
  return (
    <div class="r_t_mp3">
      <div class="left">
        <i onclick={this.playAudio} class={'icon i-' + ['bofang', 'zanting'][this.mp3.state]} />
      </div>
      <div class="right">
        <p data-label="文件名称">{this.resource.name}</p>
        <p data-label="文件大小">{this.resource.size.formatFileSize()}</p>
        <p data-label="上传时间">{new Date(this.resource.createTime).format('yyyy-MM-dd')}</p>
        <div class="progress" onclick={this.onClickProgress} style={{ '--progress': this.mp3.current_time / this.mp3.duration }} />
        <div class="times" data-current-time={this.formatAudioTime(this.mp3.current_time)} data-duration-time={this.formatAudioTime(this.mp3.duration)}>
        </div>
        <audio ref="audioRef" src={this.src} oncanplay={this.onAudioCanplay} onended={() => (this.mp3.state = 0)} />
      </div>
    </div>
  )
}

function pdf (h) {
  return (
    <div class="r_t_pdf">
      <iframe src={this.src} />

      <div class="actions">
        <i class="el-icon-full-screen" onclick={() => this.onFullScreen()} />
      </div>
    </div>
  )
}

const components = { image, audio, video, pdf }

export default {
  props: {
    timeline: { type: Boolean },
    resource: { type: Object }
  },

  data: () => ({
    src: null,
    isFullScreen: false,
    mp3: { state: 0, current_time: 0, duration: 0 },
    image: { x: 0, y: 0, s: 1, r: 0 },
    errorMsg: null
  }),

  created () {
    const type = getAcceptType(this.resource.mimetype)
    if (!type) return

    this.viewType = components[type] ? type : 'pdf'
    this.src = this.resource.preview?.fileLinkTransfer()

    if (!this.src) this.toConver(this.resource)

    window.addEventListener('resize', () => {
      this.isFullScreen = !!document.fullscreenElement
    })
  },

  methods: {
    async toConver (resource) {
      try {
        const { data } = await fileConverApi(resource.id)
        resource.preview = data
        if (this.resource === resource) this.src = data.fileLinkTransfer()
      } catch (err) {
        this.errorMsg = '文件转换失败'
      }
    },

    imageScale (s) {
      const _s = this.image.s + s * 0.2
      if (_s >= 0.6 && _s <= 2) this.image.s = _s
    },

    imageRotate (r) {
      this.image.r = this.image.r + r * 90
    },

    onFullScreen () {
      if (this.isFullScreen) {
        document.exitFullscreen()
      } else {
        this.$el.requestFullscreen()
      }
    },

    onMove (el) {
      const ox = this.image.x
      const oy = this.image.y
      const sx = el.pageX
      const sy = el.pageY
      document.body.onmouseup = () => {
        el.target.onmouseup = null
        el.target.onmousemove = null
      }
      el.target.onmousemove = (e) => {
        this.image.x = ox + e.pageX - sx
        this.image.y = oy + e.pageY - sy
      }
    },

    onClickProgress (e) {
      this.$refs.audioRef.currentTime = this.mp3.duration * e.offsetX / 300
    },

    formatAudioTime (t) {
      return `${Math.floor(t / 60).toString().padStart(2, 0)}:${Math.ceil(t % 60).toString().padStart(2, 0)}`
    },

    onAudioCanplay (e) {
      const handleTimes = ({ target }) => {
        this.mp3.current_time = target.currentTime
        this.mp3.duration = target.duration
      }
      e.target.addEventListener('timeupdate', handleTimes)
      handleTimes(e)
    },

    playAudio () {
      if (this.$refs.audioRef.paused) {
        this.$refs.audioRef.play()
        this.mp3.state = 1
      } else {
        this.$refs.audioRef.pause()
        this.mp3.state = 0
      }
    }
  },

  render (h) {
    if (!this.viewType) return <div class="no_resource_preview">该文件暂不支持预览</div>

    if (this.errorMsg) return <div class="load_file_error">{this.errorMsg}</div>

    if (!this.src) return <div class="load_file">文件加载中，请稍后...</div>

    return (
      <div class={{ resource_layout: 1, 'is-full': this.isFullScreen }}>{
        components[this.viewType]?.call(this, h)
      }</div>
    )
  },

  mixins: [
    dataReportMixin('RESOURCE_VIEW', {
      isCancelReport () { return !this.viewType },
      handleReportData () { return { field01: this.resource.id } }
    }, true)
  ]
}
</script>

<style lang="scss">
.no_resource_preview,
.load_file_error,
.load_file {
  text-align: center;
  line-height: 180px;
  color: $--color-primary;
  background-color: #fafafa;
  user-select: none;
}

.load_file_error {
  color: $--color-danger;
}

.resource_layout {
  display: flex;
  min-width: 580px;
  min-height: 150px;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  position: relative;

  .actions {
    padding: 10px;
    position: absolute;
    bottom: 12px;
    left: 50%;
    transform: translateX(-50%);
    font-size: 20px;
    color: #fff;
    background-color: rgba(0, 0, 0, .6);
    border-radius: 88px;

    i {
      margin: 0 10px;
      cursor: pointer;
    }
  }

  .r_t_image {
    img {
      display: block;
      width: 100%;
      cursor: move;
    }
  }

  .r_t_pdf {
    width: 100%;
    height: 70vh;

    iframe {
      width: 100%;
      height: 100%;
      border: 0;
    }
  }

  &.is-full .r_t_pdf {
    height: 100vh;
  }

  .r_t_mp3 {
    margin: 30px 0;
    display: flex;

    .left {
      padding: 20px;
      position: relative;
      border: 2px solid rgba($color: $--color-primary, $alpha: 0.6);
      box-shadow: 0 0 6px 1px rgba($color: $--color-primary, $alpha: 0.3);
      border-radius: 6px;
      background-color: rgba($color: $--color-primary, $alpha: 0.1);

      .icon {
        margin-top: -25px;
        margin-left: -25px;
        position: absolute;
        top: 50%;
        left: 50%;
        font-size: 50px;
        color: #fff;
      }

      &::after {
        content: '';
        display: block;
        width: 100px;
        height: 100px;
        box-shadow: inherit;
        border-radius: inherit;
        background-color: #208ac6;
      }
    }

    .right {
      margin-left: 24px;

      > p {
        margin-top: 8px;
        margin-bottom: 16px;
        width: 300px;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
        line-height: 1.3;

        &::before {
          content: attr(data-label) '：';
          color: #aaa;
        }
      }

      .progress {
        margin-top: 20px;
        margin-bottom: 6px;
        height: 8px;
        border-radius: 30px;
        background-color: #f5f5f5;
        position: relative;
        cursor: pointer;

        &::before {
          content: '';
          position: absolute;
          top: 0;
          bottom: 0;
          left: 0;
          right: calc(100% - 100% * var(--progress));
          background-color: #208ac6;
          border-radius: inherit;
        }
      }

      .times {
        display: flex;
        justify-content: space-between;
        color: #aaa;
        position: relative;

        &::before {
          content: attr(data-current-time);
        }

        &::after {
          content: attr(data-duration-time);
        }

        .icon {
          margin-left: -16px;
          padding: 10px;
          font-size: 14px;
          color: #fff;
          background-color: #87D2D9;
          background-image: linear-gradient(260deg,#40b8c3,#78d5de);
          box-shadow: 3px 4px 8px 0 #c0c4cc;
          border-radius: 50%;
          position: absolute;
          left: 50%;
          top: 6px;
          cursor: pointer;
        }
      }
    }
  }

  .r_t_mp4 {
    &,
    video {
      display: block;
      width: 100%;
      height: 100%;
      max-height: 66vh;
      background-color: #000;
    }

    video:not(.timeline)::-webkit-media-controls-timeline {
      display: none;
    }
  }

}

@keyframes rotating {
  100% {
    transform: rotate(360deg);
  }
}
</style>
