<template>
  <wrapper
    v-loading="loading"
    margin
    padding
    background
  >
    <div class="l-flex__none l-flex--row has-bottom-padding">
      <div class="l-flex__auto l-flex--row c-sibling-item">
        <button
          class="o-button"
          @click="toAdd"
        >
          <i class="o-button__icon el-icon-circle-plus-outline" />
          新增
        </button>
      </div>
      <el-select
        v-model="params.status"
        class="l-flex__none c-sibling-item o-select"
        placeholder="请选择状态"
        @change="search"
      >
        <el-option
          v-for="item in statusOptions"
          :key="item.label"
          :label="item.label"
          :value="item.value"
        />
      </el-select>
      <search-input
        v-model.trim="params.name"
        class="l-flex__none c-sibling-item"
        placeholder="节目名称"
        @search="search"
      />
      <button
        class="l-flex__none c-sibling-item o-button"
        @click="search"
      >
        搜索
      </button>
    </div>
    <status-wrapper
      v-if="isAbnormal"
      :error="error"
      @retry="getList"
    />
    <div class="c-grid">
      <div
        v-for="item in list"
        :key="item.id"
        class="l-flex--col"
      >
        <div
          class="c-program u-pointer"
          :style="item.style"
          @click="onClickProgram(item)"
        >
          <i
            v-if="item.status === 1"
            class="c-program__status el-icon-lock u-color--warning"
          />
          <i
            v-if="item.status === 2"
            class="c-program__status el-icon-circle-check u-color--success"
          />
          <span class="c-program__rate">
            {{ item.resolutionRatio }}
          </span>
          <div class="c-program__footer">
            <span class="c-program__time u-ellipsis">{{ item.createTime }}</span>
            <template v-if="item.status === 0">
              <el-tooltip
                content="提交"
                :hide-after="2000"
              >
                <i
                  class="o-icon--active el-icon-upload2 u-pointer"
                  @click.stop="onSubmit(item)"
                />
              </el-tooltip>
            </template>
            <permission
              :skip="item.status === 0"
              deletable
            >
              <el-tooltip
                content="删除"
                :hide-after="2000"
              >
                <i
                  class="o-icon--active el-icon-delete u-pointer"
                  @click.stop="onDel(item)"
                />
              </el-tooltip>
            </permission>
          </div>
        </div>
        <edit-input
          v-model.trim="item.name"
          class="c-program__name"
          :disabled="item.status !== 0"
          align="left"
          @edit="onEdit(item)"
        />
      </div>
    </div>
    <pagination
      :total="totalCount"
      :page-sizes="[8, 16, 32]"
      :page.sync="params.pageNum"
      :limit.sync="params.pageSize"
      @pagination="getList"
    />
    <el-dialog
      title="新增节目"
      :visible.sync="adding"
      custom-class="c-dialog"
      :close-on-click-modal="false"
      :before-close="handleCloseAddDialog"
    >
      <div class="c-form">
        <div class="c-form__section">
          <span class="c-form__label">名称：</span>
          <el-input
            v-model.trim="program.name"
            class="c-form__item"
            placeholder="请输入名称"
            maxlength="50"
            show-word-limit
          />
        </div>
        <div class="c-form__section">
          <span class="c-form__label">分辨率：</span>
          <el-select
            v-model="program.resolutionRatio"
            class="c-form__item"
            placeholder="请选择"
            :loading="fetching"
            popper-class="o-select-option"
          >
            <el-option
              v-for="ratio in ratios"
              :key="ratio.value"
              :label="ratio.label"
              :value="ratio.value"
            />
          </el-select>
        </div>
      </div>
      <template #footer>
        <button
          class="o-button"
          @click="add"
        >
          确定
        </button>
        <button
          class="o-button cancel"
          @click="handleCloseAddDialog"
        >
          取消
        </button>
      </template>
    </el-dialog>
  </wrapper>
</template>

<script>
import { getAssetUrl } from '@/api/asset'
import { getRatios } from '@/api/device'
import {
  getPrograms,
  addProgram,
  updateProgramName,
  deleteProgram,
  getProgram,
  submitProgram
} from '@/api/program'
import { State } from '@/constant'
import { createListOptions } from '@/utils'
import { validate } from './core/utils'

export default {
  name: 'BigScreen',
  data () {
    return {
      statusOptions: [
        { value: void 0, label: '全部状态' },
        { value: State.READY, label: '待提交' },
        { value: State.SUBMITTED, label: '未审核' },
        { value: State.RESOLVED, label: '已审核' }
      ],
      adding: false,
      program: {},
      fetching: false,
      ratios: [],
      ...createListOptions({
        pageSize: 8,
        status: void 0,
        name: ''
      }),
      disabled: false
    }
  },
  computed: {
    isAbnormal () {
      return this.error || !this.loading && this.totalCount === 0
    }
  },
  created () {
    this.getList()
    window.addEventListener('message', this.onMessage)
  },
  beforeDestroy () {
    window.removeEventListener('message', this.onMessage)
  },
  methods: {
    onMessage (event) {
      if (!this.loading) {
        const id = event.data?.id
        if (id) {
          const program = this.list.find(program => program.id === id)
          if (program) {
            program.style = this.getStyle(event.data.base64, true)
          }
        }
      }
    },
    search () {
      if (this.disabled) {
        return
      }
      this.list = []
      this.totalCount = 0
      this.params.pageNum = 1
      this.getList()
    },
    getStyle (img, base64) {
      return img ? {
        backgroundSize: 'contain',
        backgroundImage: `url("${base64 || /^data/.test(img) ? img : getAssetUrl(img)}")`
      } : {}
    },
    transform ({ id, name, status, resolutionRatio, createTime, img }) {
      return {
        id, name, status, resolutionRatio,
        style: this.getStyle(img),
        createTime: createTime?.split(' ')[0],
        originalName: name
      }
    },
    onEdit (item) {
      if (!item.name) {
        item.name = item.originalName
        return
      }

      if (item.name === item.originalName) {
        return
      }

      updateProgramName({
        id: item.id,
        name: item.name
      }).then(() => {
        item.originalName = item.name
      }, () => {
        item.name = item.originalName
      })
    },
    getList () {
      this.error = false
      this.loading = true
      getPrograms(this.params).then(({ data, totalCount }) => {
        this.list = data.map(this.transform)
        this.totalCount = totalCount
      }, () => {
        this.error = true
        this.list = []
      }).finally(() => {
        this.loading = false
      })
    },
    getRatios () {
      if (!this.fetching && this.ratios.length === 0) {
        this.fetching = true
        getRatios().then(ratios => {
          this.ratios = ratios
        }).finally(() => {
          this.fetching = false
        })
      }
    },
    toAdd () {
      if (this.disabled) {
        return
      }
      this.program = {
        name: '',
        resolutionRatio: ''
      }
      this.adding = true
      this.getRatios()
    },
    handleCloseAddDialog () {
      this.adding = false
    },
    add () {
      if (!this.program.name) {
        this.$message({
          type: 'warning',
          message: '名称不能为空'
        })
        return
      }
      if (!this.program.resolutionRatio) {
        this.$message({
          type: 'warning',
          message: '请选择分辨率'
        })
        return
      }
      addProgram(this.program).then(({ data: id }) => {
        this.handleCloseAddDialog()
        const params = this.params
        if (params.status !== void 0 && params.status !== State.READY) {
          params.status = void 0
        }
        if (params.name && !(new RegExp(params.name).test(this.program.name))) {
          params.name = ''
        }
        this.search()
        this.onDesign(id)
      })
    },
    onDesign (id) {
      const route = this.$router.resolve({
        name: 'design',
        params: { id }
      })
      window.open(route.href, '_blank')
    },
    onView (id) {
      const route = this.$router.resolve({
        name: 'view',
        params: { id }
      })
      window.open(route.href, '_blank')
    },
    onClickProgram (item) {
      const { id, status } = item
      if (status === 0) {
        this.onDesign(id)
      } else {
        this.onView(id)
      }
    },
    onSubmit (item) {
      const loading = this.$showLoading()
      getProgram(item.id).then(({ data }) => {
        const { itemJsonStr } = data
        if (!itemJsonStr) {
          this.$message({
            type: 'warning',
            message: `请先编辑节目`
          })
          return
        }
        try {
          const error = validate(JSON.parse(itemJsonStr))
          if (error) {
            this.$message({
              type: 'warning',
              message: error
            })
            return
          }
        } catch (e) {
          this.$message({
            type: 'warning',
            message: `节目数据异常`
          })
          return
        }
        submitProgram(item).then(() => {
          this.getList()
        })
      }).finally(() => {
        this.$closeLoading(loading)
      })
    },
    onDel (item) {
      deleteProgram(item).then(() => {
        if (this.list.length === 1 && this.params.pageNum > 1) {
          this.params.pageNum -= 1
        }
        this.getList()
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.c-program {
  position: relative;
  padding-top: 60%;
  color: #fff;
  font-size: 16px;
  border-radius: $radius;
  background: rgba(0, 0, 0, 0.8) url("~@/assets/program_bg.png") center center /
    100% 100% no-repeat;
  overflow: hidden;

  &__status {
    position: absolute;
    top: 6px;
    left: 6px;
    font-size: 24px;
  }

  &__rate {
    position: absolute;
    top: 0;
    right: 0;
    padding: 2px 4px;
    font-size: 12px;
    background-color: rgba(0, 0, 0, 0.5);
    border-radius: 0 0 0 4px;
  }

  &__name {
    color: $black;
    font-weight: bold;
  }

  &__footer {
    display: inline-flex;
    align-items: center;
    position: absolute;
    width: 100%;
    bottom: 0;
    padding: 24px 16px 16px;
    background-image: linear-gradient(
      to bottom,
      rgba(#000, 0) 0%,
      rgba(#000, 0.6) 100%
    );

    i {
      margin-left: $spacing;
      font-size: 18px;
    }
  }

  &__time {
    flex: 1 1 auto;
    min-width: 0;
    font-size: 14px;
  }
}
</style>
