<template>
  <wrapper
    fill
    margin
    padding
    background
  >
    <c-table
      ref="table"
      :curr="currOptions"
      row-key="id"
      @pagination="getList"
      @row-click="onRowClick"
    >
      <template #header>
        <div class="l-flex__auto c-sibling-item">
          <button
            v-if="canEdit"
            class="o-button"
            @click="onAdd"
          >
            <i class="o-button__icon el-icon-circle-plus-outline" />
            新增
          </button>
        </div>
        <el-select
          v-model="options.params.productId"
          class="l-flex__none c-sibling-item"
          placeholder="请选择产品"
          :loading="fetching"
          @visible-change="getProducts"
          @change="search"
        >
          <el-option
            v-for="item in productOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </el-select>
        <search-input
          v-model.trim="options.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>
      </template>
      <el-table-column
        width="50"
        align="center"
      >
        <template #header>
          <i
            class="o-refresh el-icon-refresh"
            @click="getList"
          />
        </template>
        <template v-slot="scope">
          <i
            v-if="scope.row.isMaster"
            class="o-expand-icon u-pointer"
            :class="{ expand: scope.row.expand, 'el-icon-arrow-right': !scope.row.loading, 'el-icon-loading': scope.row.loading }"
          />
        </template>
      </el-table-column>
      <el-table-column
        label="设备名称"
        align="center"
        min-width="120"
        show-overflow-tooltip
      >
        <template v-slot="scope">
          <span
            v-if="scope.row.empty"
            class="o-empty"
          >
            暂无备份设备
          </span>
          <template v-else>{{ scope.row.name }}</template>
        </template>
      </el-table-column>
      <el-table-column
        prop="productName"
        label="产品"
        align="center"
        min-width="120"
        show-overflow-tooltip
      />
      <el-table-column
        prop="serialNumber"
        label="序列号"
        align="center"
        min-width="120"
        show-overflow-tooltip
      />
      <el-table-column
        prop="mac"
        label="MAC"
        align="center"
        class-name="copy"
        min-width="120"
        show-overflow-tooltip
      />
      <el-table-column
        prop="resolutionRatio"
        label="分辨率"
        align="center"
        min-width="120"
      />
      <el-table-column
        label="状态"
        align="center"
        min-width="100"
      >
        <template v-slot="scope">
          <el-tag
            v-if="scope.row.activate === 0"
            class="o-tag u-pointer"
            type="warning"
            size="medium"
            @click.stop="toggleActivate(scope.row)"
          >
            未激活
          </el-tag>
          <el-tag
            v-if="scope.row.activate === 1"
            class="o-tag u-pointer"
            size="medium"
            @click.stop="toggleActivate(scope.row)"
          >
            已激活
          </el-tag>
          <el-tag
            v-if="scope.row.activate === 2"
            class="o-tag u-pointer"
            :type="scope.row.onlineStatus === 1 ? 'success' : 'danger'"
            size="medium"
            @click.stop="toggleActivate(scope.row)"
          >
            {{ scope.row.onlineStatus === 1 ? '在线' : '离线' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column
        label="操作"
        align="center"
        :width="operationColumnWidth"
      >
        <template v-slot="scope">
          <template v-if="!scope.row.empty">
            <div
              class="c-table__btn u-pointer"
              @click.stop="onEditDevice(scope.row)"
            >
              查看
            </div>
            <template v-if="canEdit">
              <div
                v-if="scope.row.isMaster"
                class="c-table__btn u-pointer"
                @click.stop="onAddSubDevice(scope.row)"
              >
                添加备份设备
              </div>
              <div
                v-if="scope.row.isMaster && scope.row.activate === 2"
                class="c-table__btn u-pointer"
                @click.stop="setDefaultProgram(scope.row)"
              >
                默认播放
              </div>
              <div
                class="c-table__btn u-pointer"
                @click.stop="onDelDevice(scope.row)"
              >
                删除
              </div>
            </template>
          </template>
        </template>
      </el-table-column>
    </c-table>
    <el-dialog
      :title="dialogTitle"
      :visible.sync="show"
      custom-class="c-dialog"
      :close-on-click-modal="false"
      :before-close="close"
    >
      <div class="c-form">
        <div class="c-form__section">
          <span class="c-form__label required">名称：</span>
          <el-input
            v-model.trim="currObj.name"
            class="c-form__item"
            maxlength="50"
            show-word-limit
          />
        </div>
        <div class="c-form__section">
          <span class="c-form__label required">产品：</span>
          <el-select
            v-model="currObj.productId"
            class="c-form__item"
            placeholder="请选择产品"
            :loading="fetching"
            :disabled="isSub"
            @visible-change="getProducts"
          >
            <el-option
              v-for="product in products"
              :key="product.value"
              :label="product.label"
              :value="product.value"
            />
          </el-select>
        </div>
        <div class="c-form__section">
          <span class="c-form__label required">序列号：</span>
          <el-input
            v-model.trim="currObj.serialNumber"
            class="c-form__item"
            maxlength="50"
          />
        </div>
        <div class="c-form__section extra o-mac">
          <span class="c-form__label required">MAC：</span>
          <el-input
            v-model.trim="currObj.mac"
            class="c-form__item"
            maxlength="17"
          />
        </div>
        <div class="c-form__section">
          <span class="c-form__label required">地址：</span>
          <el-input
            v-model="currObj.remark"
            class="c-form__item"
            type="textarea"
            :rows="3"
            maxlength="100"
            show-word-limit
          />
        </div>
      </div>
      <template #footer>
        <button
          class="o-button"
          @click="onSave"
        >
          确定
        </button>
        <button
          class="o-button cancel"
          @click="close"
        >
          取消
        </button>
      </template>
    </el-dialog>
    <el-dialog
      :visible.sync="choosing"
      title="节目选择"
      custom-class="c-dialog hidden-footer"
    >
      <event-target-choose
        v-if="choosing"
        :ratio="ratio"
        @choose="onChoose"
      />
    </el-dialog>
  </wrapper>
</template>

<script>
import {
  getDevices,
  addDevice,
  deleteDevice,
  updateDevice,
  getSubDevices,
  addSubDevice,
  activateDevice,
  deactivateDevice,
  getProducts
} from '@/api/device'
import { publish } from '@/api/publish'
import {
  EventPriority,
  EventFreq,
  PublishType
} from '@/constant'
import { createListOptions } from '@/utils'
import { toDateStr } from '@/utils/event'
import mixin from './mixins'
import EventTargetChoose from '@/components/EventTargetChoose'

export default {
  name: 'DeviceList',
  components: {
    EventTargetChoose
  },
  mixins: [mixin],
  data () {
    return {
      proxy: {
        list: getDevices,
        add: addDevice,
        update: updateDevice,
        del: deleteDevice
      },
      options: createListOptions({
        productId: '',
        name: ''
      }),
      productOptions: [
        { value: '', label: '全部设备' }
      ],
      loaded: false,
      fetching: false,
      firstLoadSize: 999,
      isSub: false,
      device: null,
      choosing: false,
      ratio: null
    }
  },
  computed: {
    canEdit () {
      return this.accessSet.has(this.Access.MANAGE_DEVICES)
    },
    canEditDefaultProgram () {
      return this.canEdit || this.accessSet.has(this.Access.MANAGE_DEVICE)
    },
    operationColumnWidth () {
      return this.canEdit ? 340 : this.canEditDefaultProgram ? 260 : 120
    },
    type () {
      return this.isSub ? '备份设备' : '设备'
    },
    products () {
      return this.isSub
        ? [{ value: this.$master.productId, label: this.$master.productName }]
        : this.loaded
          ? this.productOptions.slice(1)
          : []
    },
    tableData () {
      const arr = []
      this.list.forEach(item => {
        arr.push(item)
        if (item.loaded && item.expand) {
          arr.push(...item.subs)
        }
      })
      return arr
    },
    currOptions () {
      const arr = []
      this.options.list.forEach(item => {
        arr.push(item)
        if (item.loaded && item.expand) {
          arr.push(...item.subs)
        }
      })
      return {
        ...this.options,
        list: arr
      }
    }
  },
  activated () {
    this.getList()
  },
  methods: {
    _getProducts () {
      this.fetching = true
      getProducts({ pageNum: 1, pageSize: this.firstLoadSize }).then(({ data, totalCount }) => {
        if (totalCount > this.firstLoadSize) {
          this.firstLoadSize = totalCount
          this._getProducts()
        } else {
          this.productOptions = this.productOptions.concat(data.map(({ id, name }) => {
            return { value: id, label: name }
          }))
          this.fetching = false
          this.loaded = true
        }
      }, () => {
        this.fetching = false
      })
    },
    getProducts (visible) {
      if (visible && !this.fetching && !this.loaded) {
        this._getProducts()
      }
    },
    onRowClick (row) {
      if (row.isMaster) {
        if (row.loaded) {
          row.expand = !row.expand
        } else if (!row.loading) {
          this.getSubDevices(row)
        }
      }
    },
    getDefaults () {
      return {
        name: '',
        productId: this.isSub && this.$master.productId || this.options.params.productId,
        serialNumber: '',
        mac: '',
        remark: ''
      }
    },
    transform (data) {
      return data.map(item => {
        return {
          ...item,
          loaded: false,
          loading: false,
          expand: false,
          subs: [],
          isMaster: true
        }
      })
    },
    getSubDevices (item, pageSize = 999) {
      item.loading = true
      getSubDevices({
        id: item.id,
        pageNum: 1,
        pageSize
      }).then(({ data, totalCount }) => {
        if (totalCount > pageSize) {
          this.getSubDevices(item, totalCount)
        } else {
          item.loading = false
          item.loaded = true
          item.expand = true
          if (data.length === 0) {
            item.subs = [{ id: `${Math.random()}`, empty: true }]
          } else {
            item.subs = data.map(device => {
              return {
                ...device,
                isMaster: false,
                empty: false,
                parent: item
              }
            })
          }
        }
      }, () => {
        item.loading = false
      })
    },
    afterAdd () {
      const params = this.options.params
      if (params.name && !(new RegExp(params.name).test(this.currObj.name))) {
        params.name = ''
      }
      if (params.productId && params.productId !== this.currObj.productId) {
        params.productId = ''
      }
    },
    check (item) {
      if (!item.name) {
        this.$message({
          type: 'warning',
          message: '名称不能为空'
        })
        return false
      }
      if (!item.productId) {
        this.$message({
          type: 'warning',
          message: '请选择产品'
        })
        return false
      }
      if (!item.serialNumber) {
        this.$message({
          type: 'warning',
          message: '序列号不能为空'
        })
        return false
      }
      if (!item.mac) {
        this.$message({
          type: 'warning',
          message: 'MAC不能为空'
        })
        return false
      }
      if (!/^[0-9a-fA-F]{2}(:[0-9a-fA-F]{2}){5}$/.test(item.mac)) {
        this.$message({
          type: 'warning',
          message: 'MAC格式不正确，例 ff:ff:ff:ff:ff:ff'
        })
        return false
      }
      item.mac = item.mac.toLowerCase()
      if (!item.remark) {
        this.$message({
          type: 'warning',
          message: '地址不能为空'
        })
        return false
      }
      return true
    },
    close () {
      this.isSub = false
      this.$device = null
      this.show = false
    },
    onAddSubDevice (item) {
      this.isSub = true
      this.$master = item
      this.onAdd()
    },
    onEditDevice (item) {
      this.$router.push({
        name: 'device-detail',
        params: {
          id: item.id
        }
      })
    },
    reloadSubDevices (item) {
      item.loaded = false
      item.children = []
      this.getSubDevices(item)
    },
    onSave () {
      if (this.isSub) {
        if (this.check(this.currObj)) {
          addSubDevice(this.$master, this.currObj).then(() => {
            this.reloadSubDevices(this.$master)
            this.close()
          })
        }
      } else {
        this.save()
      }
    },
    onDelDevice (item) {
      if (item.isMaster) {
        this.onDel(item)
      } else {
        this.proxy.del(item).then(() => {
          this.reloadSubDevices(item.parent)
        })
      }
    },
    toggleActivate (item) {
      (item.activate ? deactivateDevice : activateDevice)(item).then(() => {
        if (item.isMaster) {
          this.getList()
        } else {
          this.reloadSubDevices(item.parent)
        }
      })
    },
    setDefaultProgram (device) {
      this.ratio = device.resolutionRatio
      this.$device = {
        id: device.id,
        name: device.name
      }
      this.choosing = true
    },
    onChoose (target) {
      this.$confirm(`确定将设备 ${this.$device.name} 的默认播放设置为 ${target.name}？`).then(() => {
        return publish(
          [this.$device.id],
          {
            type: PublishType.EVENT,
            detail: {
              priority: EventPriority.DEFAULT,
              freq: EventFreq.ONCE,
              start: `${toDateStr(new Date())} 00:00:00`,
              until: null,
              target
            }
          },
          {
            programCalendarName: target.name,
            resolutionRatio: this.ratio
          }
        )
      }).then(() => {
        this.choosing = false
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.o-item {
  display: block;
  margin-right: 0;
  margin-bottom: 0;

  ::v-deep {
    label {
      width: 90px;
      color: #99a9bf;
    }
  }
}

.o-expand-icon {
  transition: transform 0.2s;

  &.expand {
    transform: rotate(90deg);
  }
}

.o-empty {
  color: $gray;
  font-size: 14px;
}

.o-mac::after {
  content: "例: ff:ff:ff:ff:ff:ff";
}
</style>
