<template>
  <div class="l-flex--col">
    <div class="c-sibling-item--v has-bottom-padding--sm has-bottom-border">
      <div class="c-sibling-item--v u-bold">
        <span class="c-sibling-item u-font-size--sm">上播内容</span>
        <i
          v-if="isAssets"
          class="c-sibling-item el-icon-edit u-color--blue u-pointer"
          @click="onEditAssets"
        />
      </div>
      <div
        v-if="!simple"
        class="l-flex--row c-sibling-item--v near"
      >
        <el-select
          v-model="currentTarget.type"
          class="c-sibling-item"
          @change="onChangeTargetType"
        >
          <el-option
            v-for="option in eventTypeOptions"
            :key="option.value"
            :label="option.label"
            :value="option.value"
          />
        </el-select>
        <div
          v-if="isAssets"
          class="c-sibling-item o-button"
          @click="onImportDataset"
        >
          导入
        </div>
        <div
          class="l-flex--row c-sibling-item far has-active u-ellipsis"
          @click="onViewCurrentTarget"
        >
          {{ targetInfo }}
        </div>
      </div>
    </div>
    <template v-if="isAssets">
      <draggable
        v-if="currentTarget.assets.length"
        v-model="currentTarget.assets"
        class="l-flex__fill c-sibling-item--v u-overflow-y--auto"
        handle=".mover"
        animation="300"
      >
        <draggable-item
          v-for="(asset, index) in currentTarget.assets"
          :key="asset.key"
          :item="asset"
          :hide-duration="hideDuration"
          @view="onViewAsset"
          @del="onDelAsset(index)"
        />
      </draggable>
      <el-empty
        v-else
        class="l-flex__fill l-flex--row center"
        description="请添加素材"
      />
    </template>
    <schema-table
      v-else
      :key="currentTarget.type"
      class="c-sibling-item--v"
      :schema="schema"
      row-key="id"
      :current-row-key="selectedId"
      highlight-current-row
      @row-click="onClickRow"
    />
    <confirm-dialog
      ref="assetTableDialog"
      title="上播内容"
      size="xl fixed"
      append-to-body
      @confirm="onSaveAssets"
    >
      <c-transfer
        class="l-flex__auto"
        :source-schema="assetTableSchema"
        :add="onAddAssets"
      >
        <el-empty
          v-if="!selectionAssets.length"
          class="l-flex__auto l-flex--row center"
          description="请添加素材"
        />
        <draggable
          v-else
          v-model="selectionAssets"
          class="l-flex__auto l-flex--col u-font-size--sm u-overflow-y--auto"
          handle=".mover"
          animation="300"
        >
          <draggable-item
            v-for="(asset, index) in selectionAssets"
            :key="asset.key"
            :item="asset"
            @view="onViewAsset"
            @del="onDelSelectionAsset(index)"
          />
        </draggable>
      </c-transfer>
    </confirm-dialog>
    <radio-table-dialog
      ref="datasetDialog"
      title="素材包"
      message="请选择素材包"
      :schema="datasetSchema"
      append-to-body
      @confirm="onChoosenDataset"
    />
    <table-dialog
      ref="contentDialog"
      title="素材包"
      :schema="contentSchema"
      append-to-body
    />
    <preview-dialog ref="previewDialog" />
    <material-dialog ref="materialDialog" />
  </div>
</template>

<script>
import {
  State,
  ScheduleType,
  EventTarget,
  EventTargetInfo,
  AssetTagInfo,
  AssetType,
  AssetTypeInfo,
  Dataset
} from '@/constant'
import {
  parseDuration,
  getAssetThumb,
  getAssetDuration
} from '@/utils'
import { getRatios } from '@/api/device'
import {
  getDatasets,
  getCommonDataset
} from '@/api/asset'
import { getSchedules } from '@/api/calendar'
import { getPrograms } from '@/api/program'
import { assetTableMixin } from '@/mixins/asset-table'
import Draggable from 'vuedraggable'

export default {
  name: 'EventTargetPicker',
  components: {
    Draggable
  },
  mixins: [assetTableMixin],
  props: {
    eventTarget: {
      type: Object,
      default: null
    },
    simple: {
      type: [Boolean, String],
      default: false
    },
    ratio: {
      type: String,
      default: ''
    }
  },
  data () {
    return {
      eventTypeOptions: [
        { value: EventTarget.PROGRAM, label: EventTargetInfo[EventTarget.PROGRAM] },
        { value: EventTarget.RECUR, label: EventTargetInfo[EventTarget.RECUR] },
        { value: EventTarget.ASSETS, label: EventTargetInfo[EventTarget.ASSETS] }
      ],
      currentTarget: null,
      selectionAssets: [],
      datasetSchema: {
        list: getDatasets,
        condition: { type: Dataset.COMMON },
        cols: [
          { prop: 'name', label: '名称', 'align': 'center' },
          { type: 'invoke', render: [
            { label: '查看', on: this.onViewDataset }
          ] }
        ]
      },
      contentSchema: {
        singlePage: true,
        list: this.getAssets,
        cols: [
          { prop: 'tagInfo', label: '类型', align: 'center', width: 80 },
          { prop: 'typeName', label: '文件', align: 'center', width: 80 },
          { prop: 'file', label: '', type: 'asset', on: this.onViewAsset },
          { prop: 'name', label: '' },
          { prop: 'duration', label: '上播时长', 'align': 'center', width: 100 },
          { type: 'invoke', render: [
            { label: '查看', on: this.onViewAsset }
          ] }
        ]
      }
    }
  },
  computed: {
    isAssets () {
      return this.currentTarget?.type === EventTarget.ASSETS
    },
    hideDuration () {
      return this.isAssets && this.currentTarget.assets.length <= 1
    },
    selectedId () {
      return this.currentTarget?.detail?.id
    },
    targetInfo () {
      if (this.isAssets) {
        return ''
      }
      return this.currentTarget?.detail
        ? this.currentTarget.detail.name || '未知'
        : ''
    },
    schema () {
      if (!this.currentTarget) {
        return {}
      }
      const { type } = this.currentTarget

      return {
        list: this.getListInvoke,
        condition: { resolutionRatio: this.ratio, name: '' },
        filters: [
          { key: 'resolutionRatio', type: 'select', placeholder: '分辨率', remote: getRatios },
          { key: 'name', type: 'search', placeholder: '名称' }
        ],
        cols: [
          { render: ({ id }, h) => h(
            'span',
            { staticClass: `el-radio__input ${id === this.selectedId ? 'is-checked' : ''}` },
            [h('span', { staticClass: 'el-radio__inner' })]
          ), width: 60, align: 'center' },
          type === EventTarget.PROGRAM
            ? { label: '缩略图', type: 'asset', render ({ img }) {
              return img
                ? { thumb: img }
                : null
            }, on: this.onView }
            : null,
          { prop: 'name', label: '名称' },
          { prop: 'resolutionRatio', label: '分辨率' },
          { type: 'invoke', render: [
            { label: '查看', on: this.onView }
          ] }
        ]
      }
    }
  },
  watch: {
    eventTarget: {
      handler () {
        this.init()
      },
      immediate: true
    }
  },
  methods: {
    init () {
      const target = this.eventTarget

      switch (target?.type) {
        case EventTarget.PROGRAM:
        case EventTarget.RECUR:
          this.currentTarget = {
            type: target.type,
            detail: target,
            assets: []
          }
          break
        case EventTarget.ASSETS:
          this.currentTarget = {
            type: target.type,
            detail: null,
            assets: (target.sources || []).map(asset => {
              return {
                info: `${AssetTagInfo[asset.tag]} ${AssetTypeInfo[asset.type]}`,
                ...asset
              }
            })
          }
          break
        default:
          this.currentTarget = {
            type: EventTarget.PROGRAM,
            detail: null,
            assets: []
          }
          break
      }
    },
    onChangeTargetType () {
      this.currentTarget.detail = null
      this.currentTarget.assets = []
    },
    getListInvoke (params) {
      switch (this.currentTarget.type) {
        case EventTarget.RECUR:
          return getSchedules({
            type: ScheduleType.RECUR,
            status: State.AVAILABLE,
            ...params
          })
        default:
          return getPrograms({
            status: State.AVAILABLE,
            ...params
          })
      }
    },
    onView ({ id }) {
      switch (this.currentTarget.type) {
        case EventTarget.PROGRAM:
          this.$refs.materialDialog.showProgram(id)
          break
        case EventTarget.RECUR:
          this.$refs.materialDialog.showSchedule(id)
          break
        default:
          break
      }
    },
    onViewCurrentTarget () {
      this.onView(this.currentTarget.detail)
    },
    onClickRow (row) {
      this.currentTarget.detail = row
    },
    onEditAssets () {
      this.selectionAssets = this.currentTarget.assets.map(asset => {
        return {
          ...asset
        }
      })
      this.$refs.assetTableDialog.show()
    },
    onDelSelectionAsset (index) {
      this.selectionAssets.splice(index, 1)
    },
    onAddAssets (value) {
      value.forEach(item => {
        const { tag, type, keyName, originalName, size, md5, file } = item
        this.selectionAssets.push({
          key: `${Date.now()}_${Math.random().toString(16).slice(2)}`,
          tag,
          type,
          keyName,
          size,
          md5,
          info: `${AssetTagInfo[tag]} ${AssetTypeInfo[type]}`,
          name: originalName,
          duration: getAssetDuration(item),
          disabled: type === AssetType.VIDEO,
          file
        })
      })
      return Promise.resolve()
    },
    onSaveAssets (done) {
      this.currentTarget.assets = this.selectionAssets.map(asset => {
        return {
          ...asset
        }
      })
      done()
    },
    onImportDataset () {
      this.$datasetAssets = null
      this.$refs.datasetDialog.show()
    },
    onViewDataset ({ id }) {
      this.$datasetId = id
      this.$datasetAssets = null
      this.$refs.contentDialog.show()
    },
    getAssets () {
      if (this.$datasetAssets) {
        return Promise.resolve({ data: this.$datasetAssets })
      }
      return getCommonDataset(this.$datasetId).then(({ data: { mediaList } }) => {
        this.$datasetAssets = mediaList.map(this.transformDatasetAsset)
        return {
          data: this.$datasetAssets
        }
      })
    },
    transformDatasetAsset (asset) {
      asset.tagInfo = AssetTagInfo[asset.tag]
      asset.typeName = AssetTypeInfo[asset.type]
      asset.file = {
        type: asset.type,
        url: asset.keyName,
        thumb: asset.minioData ? getAssetThumb(asset.minioData) : null
      }
      asset.name = asset.minioData?.originalName || '素材已删除'
      asset.duration = parseDuration(asset.adDuration)
      return asset
    },
    onChoosenDataset ({ value, done }) {
      if (this.$datasetId !== value.id) {
        this.$datasetId = value.id
        this.$datasetAssets = null
      }
      this.getAssets().then(({ data }) => {
        data.forEach(item => {
          const { tag, type, keyName, adDuration, name, file, minioData } = item
          if (minioData) {
            this.currentTarget.assets.push({
              key: `${Date.now()}_${Math.random().toString(16).slice(2)}`,
              tag,
              type,
              keyName,
              size: minioData.size,
              md5: minioData.md5,
              info: `${AssetTagInfo[tag]} ${AssetTypeInfo[type]}`,
              name,
              duration: adDuration,
              disabled: type === AssetType.VIDEO,
              file
            })
          }
        })
        done()
      })
    },
    onDelAsset (index) {
      this.currentTarget.assets.splice(index, 1)
    },
    createEventTarget () {
      if (this.isAssets ? !this.currentTarget.assets.length : !this.selectedId) {
        this.$message({
          type: 'warning',
          message: '请选择上播内容'
        })
        return null
      }
      const { type, detail, assets } = this.currentTarget
      return type === EventTarget.PROGRAM
        ? {
          type,
          id: detail.id,
          name: detail.name,
          programUrl: `${detail.buckets}/${detail.itemConfigName}`
        }
        : type === EventTarget.RECUR
          ? {
            type,
            id: detail.id,
            name: detail.name
          }
          : {
            type,
            sources: assets.map(({ tag, type, name, keyName, duration, size, md5 }) => {
              return { tag, type, name, keyName, duration, size, md5 }
            })
          }
    },
    getSnapshot () {
      return this.currentTarget
    },
    getValue () {
      const eventTarget = this.createEventTarget()
      if (eventTarget && !this.isAssets && (!this.ratio || this.ratio !== this.currentTarget.detail.resolutionRatio)) {
        eventTarget.adaptive = 1
      }
      return eventTarget
    }
  }
}
</script>
