<template>
  <wrapper
    fill
    margin
    padding
    background
  >
    <schema-table
      ref="table"
      :schema="schema"
    />
    <confirm-dialog
      ref="addDialog"
      title="新增合同"
      @confirm="onSave"
    >
      <div class="c-grid-form u-align-self--center">
        <span class="c-grid-form__label required">名称</span>
        <el-input
          v-model.trim="defaultName"
          placeholder="最多50个字符"
          maxlength="50"
          clearable
        />
      </div>
    </confirm-dialog>
    <confirm-dialog
      ref="editDialog"
      :title="contractName"
      size="large fixed"
      @confirm="onSaveEdit"
    >
      <div class="l-flex__fill l-flex">
        <div class="l-flex__none l-flex--col c-sibling-item">
          <div class="c-contract-dialog__header u-bold">基本数据（影响初次导入）</div>
          <div class="l-flex__fill u-overflow-y--auto">
            <div
              v-if="contract"
              class="c-grid-form mini"
            >
              <div class="c-grid-form__label">上刊日期</div>
              <div class="l-flex--row c-event__option">
                <el-date-picker
                  v-model="contract.date"
                  type="daterange"
                  range-separator="至"
                  value-format="yyyy-MM-dd"
                  :editable="false"
                  :clearable="false"
                />
              </div>
              <div class="c-grid-form__label">上播方式</div>
              <schema-select
                v-model="contract.time.type"
                :schema="timeTypeSelectSchema"
              />
              <template v-if="contract.time.type === 2">
                <div class="c-grid-form__label">时段</div>
                <el-time-picker
                  key="range-picker"
                  v-model="contract.time.range"
                  is-range
                  format="HH:mm"
                  value-format="HH:mm"
                  :clearable="false"
                />
              </template>
              <template v-if="contract.time.type === 3">
                <div class="c-grid-form__label">时间点</div>
                <el-time-picker
                  key="time-picker"
                  v-model="contract.time.point"
                  value-format="HH:mm:ss"
                  :clearable="false"
                />
              </template>
              <div class="c-grid-form__label">上播时长(s)</div>
              <el-input-number
                v-model="contract.duration"
                class="c-grid-form__info"
                data-info="范围：1~86400"
                :min="1"
                :max="86400"
                step-strictly
              />
              <div class="c-grid-form__label">上播次数</div>
              <el-input-number
                v-model="contract.count"
                :min="1"
                step-strictly
              />
              <div class="c-grid-form__label">关联的文件</div>
              <div class="c-grid-form__option">
                <el-upload
                  ref="upload"
                  class="c-contract-dialog__upload"
                  action="none"
                  :auto-upload="false"
                  :show-file-list="false"
                  :on-change="onChange"
                >
                  <i class="el-icon-plus" />
                </el-upload>
                <div>
                  <div
                    v-for="(file, index) in files"
                    :key="file.id"
                    class="l-flex--row c-contract-dialog__file"
                  >
                    <i
                      class="l-flex__none c-contract-dialog__del mini el-icon-minus has-active u-pointer"
                      @click="onDelFile(file, index)"
                    />
                    <div
                      class="l-flex__fill has-active u-ellipsis u-pointer"
                      @click="onDownload(file)"
                    >{{ file.name }}</div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
        <div class="l-flex__fill l-flex--col c-sibling-item far">
          <div class="l-flex--row c-contract-dialog__header">
            <span class="c-sibling-item u-bold">上播内容</span>
            <i
              class="c-sibling-item el-icon-circle-plus-outline u-color--blue u-pointer"
              @click="onAddAsset"
            />
          </div>
          <draggable
            v-model="assets"
            class="l-flex__fill u-overflow-y--auto"
            handle=".mover"
            animation="300"
          >
            <div
              v-for="(asset, index) in assets"
              :key="asset.key"
              class="l-flex--row c-sibling-item--v c-contract-dialog__item"
            >
              <div class="l-flex__auto l-flex--row mover">
                <i class="l-flex__none c-contract-dialog__mover el-icon-sort has-active" />
                <div
                  class="l-flex__auto c-contract-dialog__name u-ellipsis has-active u-pointer"
                  @click="onViewAssetItem(asset)"
                >
                  {{ asset.tagInfo }} {{ asset.name }}
                </div>
              </div>
              <template v-if="needDuration">
                <span class="l-flex__none u-color--info">上播时长(s)：</span>
                <el-input-number
                  v-model="asset.duration"
                  class="l-flex__none c-contract-dialog__seconds"
                  controls-position="right"
                  :min="1"
                  :max="86400"
                  :step="1"
                  :disabled="asset.disabled"
                  step-strictly
                />
              </template>
              <i
                class="l-flex__none c-contract-dialog__del el-icon-delete has-active u-pointer"
                @click="onDelAsset(asset, index)"
              />
            </div>
          </draggable>
        </div>
      </div>
    </confirm-dialog>
    <table-dialog
      ref="assetTableDialog"
      title="上播内容选择"
      :schema="assetTableSchema"
      @choosen="onChoosenAsset"
    />
    <preview-dialog ref="previewDialog" />
  </wrapper>
</template>

<script>
import {
  AssetTagInfo,
  AssetType,
  TimeType,
  SCREEN_TIME_KEY
} from '@/constant'
import {
  parseTime,
  parseDuration,
  parseTaskTime,
  getTaskTimeInfo,
  transformToTaskTime,
  offsetDate,
  calculateDay,
  getAssetDuration
} from '@/utils'
import {
  getAssetUrl,
  getContracts,
  addContract,
  updateContract,
  getContract,
  deleteContract,
  bindFileToContract,
  deleteFileFromContract
} from '@/api/asset'
import { assetTableMixin } from '@/mixins/asset-table'
import Draggable from 'vuedraggable'

export default {
  name: 'AdContract',
  components: {
    Draggable
  },
  mixins: [assetTableMixin],
  data () {
    return {
      schema: {
        buttons: [
          { type: 'add', on: this.onAdd }
        ],
        list: getContracts,
        transform: this.transform,
        cols: [
          { prop: 'name', label: '名称', render: (data, h) => h('edit-input', {
            props: {
              value: `${data.name}`,
              maxlength: 50
            },
            on: { edit: val => this.onEditName(data, val) }
          }), 'min-width': 160 },
          { prop: 'dateRange', label: '上刊日期', 'width': 240 },
          { prop: 'timeRange', label: '上播时间', 'min-width': 100 },
          { prop: 'count', label: '上播次数', 'min-width': 100 },
          { prop: 'durationInfo', label: '上播时长', 'min-width': 100 },
          { type: 'invoke', render: [
            { label: '详情', on: this.onEdit },
            { label: '删除', on: this.onDel }
          ] }
        ]
      },
      defaultName: '',
      contract: null,
      timeTypeSelectSchema: {
        options: [
          { value: TimeType.SCREEN, label: '开机期间' },
          { value: TimeType.RANGE, label: '时段' },
          { value: TimeType.POINT, label: '时间点' }
        ]
      },
      files: [],
      assets: []
    }
  },
  computed: {
    contractName () {
      return this.contract?.name
    },
    needDuration () {
      return this.assets.length > 1
    }
  },
  methods: {
    onAdd () {
      this.defaultName = ''
      this.$refs.addDialog.show()
    },
    onSave (done) {
      if (!this.defaultName) {
        this.$message({
          type: 'warning',
          message: '请填写合同名称'
        })
        return
      }
      addContract({
        name: this.defaultName,
        startDate: parseTime(new Date(), '{y}-{m}-{d}'),
        day: 1,
        startTime: SCREEN_TIME_KEY,
        endTime: SCREEN_TIME_KEY,
        duration: 5,
        count: 100
      }).then(() => {
        done()
        this.$refs.table.pageTo()
      })
    },
    transform (contract) {
      contract.durationInfo = parseDuration(contract.duration)
      contract.dateRange = `${contract.startDate} 至 ${offsetDate(contract.startDate, contract.day)}`
      contract.timeRange = getTaskTimeInfo(contract)
      return contract
    },
    onEditName (contract, { newVal, oldVal }) {
      if (newVal === oldVal) {
        return
      }
      if (!newVal) {
        this.$message({
          type: 'warning',
          message: '请填写合同名称'
        })
        return
      }
      contract.name = newVal
      updateContract(contract.id, {
        attrs: {
          name: newVal
        }
      }).catch(() => {
        contract.name = oldVal
      })
    },
    onEdit (contract) {
      getContract(contract.id).then(({ data: { files, assets, ...data } }) => {
        this.$contract = contract
        this.contract = {
          ...data,
          date: [data.startDate, offsetDate(data.startDate, data.day)],
          time: parseTaskTime({ startTime: data.startTime, endTime: data.endTime })
        }
        this.files = files
        this.$assetMap = {}
        this.assets = assets.map(({ id, keyName, orderNo, duration, minioData }) => {
          this.$assetMap[id] = `${orderNo}_${duration}`
          return {
            key: id,
            id,
            tagInfo: AssetTagInfo[minioData.tag],
            type: minioData.type,
            keyName,
            name: minioData.originalName,
            duration,
            disabled: minioData.type === AssetType.VIDEO
          }
        })
        this.$refs.editDialog.show()
      })
    },
    onSaveEdit (done) {
      const { date, time, duration, count } = this.contract
      const attrs = {
        ...transformToTaskTime(time),
        startDate: date[0],
        day: calculateDay(date[0], date[1]) + 1,
        duration,
        count
      }
      const data = {}
      if (['startDate', 'day', 'startTime', 'endTime', 'duration', 'count'].some(key => attrs[key] !== this.$contract[key])) {
        data.attrs = attrs
      }
      let totalDuration = 0
      const delIdMap = {
        ...this.$assetMap
      }
      const assets = this.assets.map(({ id, keyName, duration }, index) => {
        totalDuration += duration
        const data = {
          keyName,
          duration,
          orderNo: index
        }
        if (id) {
          data.id = id
        }
        return data
      }).filter(({ id, orderNo, duration }) => {
        if (id) {
          delete delIdMap[id]
          console.log(`${orderNo}_${duration}`, this.$assetMap[id])
          if (`${orderNo}_${duration}` === this.$assetMap[id]) {
            return false
          }
        }
        return true
      })
      if (assets.length > 0) {
        data.assets = assets
      }
      const delIds = Object.keys(delIdMap)
      if (delIds.length > 0) {
        data.deleteIds = delIds
      }
      if (this.assets.length > 1 && totalDuration % duration !== 0) {
        this.$confirm(
          '上播时长与上播内容总时长不一致，上播内容无法完整播放',
          '继续保存',
          { type: 'warning' }
        ).then(() => {
          this.updateContract(data, done)
        })
        return
      }
      this.updateContract(data, done)
    },
    updateContract (data, done) {
      if (!Object.keys(data).length) {
        done()
        return
      }
      updateContract(this.$contract.id, data).then(() => {
        done()
        if (data.attrs) {
          this.transform(Object.assign(this.$contract, data.attrs))
        }
      })
    },
    onAddAsset () {
      this.$refs.assetTableDialog.show()
    },
    onChoosenAsset ({ value, done }) {
      const { tag, type, keyName, originalName } = value
      this.assets.push({
        key: `${Date.now()}_${Math.random().toString(16).slice(2)}`,
        tagInfo: AssetTagInfo[tag],
        disabled: type === AssetType.VIDEO,
        name: originalName,
        type,
        keyName,
        duration: getAssetDuration(value)
      })
      done()
    },
    onDelAsset (asset, index) {
      this.assets.splice(index, 1)
    },
    onChange ({ raw }) {
      this.$refs.upload.clearFiles()
      bindFileToContract(this.$contract.id, raw).then(({ data }) => {
        this.files.push(data)
      })
    },
    onDelFile (file, index) {
      deleteFileFromContract(file).then(() => {
        this.files.splice(index, 1)
      })
    },
    onDownload (file) {
      const a = document.createElement('a')
      a.style.display = 'none'
      a.setAttribute('target', '_blank')
      a.setAttribute('download', file.name)
      a.href = getAssetUrl(file.enclosureUrl)
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
    },
    onDel (contract) {
      deleteContract(contract).then(() => {
        this.$refs.table.decrease(1)
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.c-contract-dialog {
  &__header {
    padding-bottom: 8px;
    margin-bottom: $spacing;
    color: $black;
    font-size: 18px;
    line-height: 1;
    border-bottom: 1px solid $border;
  }

  &__item {
    padding: 4px 0;
    border: 1px solid $gray;
    border-radius: $radius--mini;

    &.sortable-chosen {
      border-color: #c6e2ff;
      background-color: $blue--light;
    }
  }

  &__mover {
    padding: 10px 16px;
    font-size: 18px;
    cursor: move;
  }

  &__name {
    padding: 16px 10px 16px 0;
  }

  &__seconds {
    width: 120px;
  }

  &__del {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    width: 50px;
    height: 40px;
    color: $gray;
    font-size: 18px;

    &.mini {
      width: 40px;
    }

    &:hover {
      color: $primary;
    }
  }

  &__upload {
    display: inline-block;
    border: 1px dashed #c0ccda;
    border-radius: 6px;
    background-color: #fbfdff;
    cursor: pointer;

    ::v-deep {
      .el-upload {
        display: inline-flex;
        justify-content: center;
        align-items: center;
        width: 40px;
        height: 40px;
      }
    }

    &:hover {
      color: $blue;
      border-color: $blue;
    }
  }

  &__file {
    width: 350px;

    & + & {
      border-top: 1px solid $border;
    }
  }
}
</style>
