<template>
  <div
    v-loading="loading"
    class="l-flex--col"
  >
    <template v-if="!loading">
      <warning
        v-if="error"
        @click="getDefaults"
      />
      <template v-else-if="info">
        <div class="c-info">
          <div class="l-flex--row c-info__block">
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">厂商名称</div>
              <schema-select
                v-model="info.manufacturerKey"
                class="l-flex__fill c-info__value"
                :schema="manufacturerSelectSchema"
                @change="onChangeProp('manufacturerKey')"
              />
            </div>
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">
                拓扑结构
                <i
                  class="o-icon medium el-icon-view has-active"
                  @click="onView"
                />
              </div>
              <el-upload
                ref="upload"
                class="l-flex__fill o-upload"
                action="none"
                :auto-upload="false"
                :show-file-list="false"
                :on-change="onChangeTopology"
                drag
              >
                <div class="u-color--black">已上传</div>
              </el-upload>
            </div>
          </div>
          <div class="l-flex--row c-info__block">
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">设备型号</div>
              <edit-input
                v-model.trim="info.screen"
                class="l-flex__fill c-info__value"
                @edit="onChangeProp('screen')"
              />
            </div>
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">设备IP</div>
              <edit-input
                v-model.trim="info.ip"
                class="l-flex__fill c-info__value"
                @edit="onChangeProp('ip')"
              />
            </div>
          </div>
          <div class="l-flex--row c-info__block">
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">异步盒</div>
              <div class="l-flex__fill">
                <el-switch
                  v-model="info.async"
                  active-color="#13ce66"
                  inactive-color="#ff4949"
                  @change="onChangeProp('async')"
                />
              </div>
            </div>
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">温度监测</div>
              <div class="l-flex__fill">
                <el-switch
                  v-model="info.temperature"
                  active-color="#13ce66"
                  inactive-color="#ff4949"
                  @change="onChangeProp('temperature')"
                />
              </div>
            </div>
          </div>
          <div class="l-flex--row c-info__block">
            <div class="l-flex--row l-flex__fill c-info__item">
              <div class="l-flex__none c-info__title">电压监测</div>
              <div class="l-flex__fill">
                <el-switch
                  v-model="info.voltage"
                  active-color="#13ce66"
                  inactive-color="#ff4949"
                  @change="onChangeProp('voltage')"
                />
              </div>
            </div>
          </div>
        </div>
        <el-dialog
          :visible.sync="showTopology"
          custom-class="c-dialog--detail"
          title="拓扑图"
          :close-on-click-modal="false"
        >
          <receiving-card-topology
            v-if="showTopology"
            class="l-flex__auto"
            :info="info"
          />
        </el-dialog>
      </template>
      <template v-else>
        <div class="l-flex__fill l-flex--row center">
          <div class="l-flex--col center">
            <button
              class="o-button"
              @click="onBind"
            >
              绑定接收卡
            </button>
          </div>
        </div>
        <confirm-dialog
          ref="addDialog"
          title="绑定接收卡"
          @confirm="onSave"
        >
          <el-upload
            ref="uploadTopology"
            class="o-upload has-bottom-padding"
            action="none"
            :auto-upload="false"
            :show-file-list="false"
            :on-change="onChange"
            drag
          >
            <div class="l-flex--row">
              <template v-if="receivingCard.topologyFile">
                <div class="o-upload__file">{{ receivingCard.topologyFile.name }}</div>
              </template>
              <template v-else>
                添加拓扑结构文件将文件拖动到本窗口上传或
                <span class="o-upload__tip">点击选择文件</span>
              </template>
            </div>
          </el-upload>
          <div class="c-grid-form u-align-self--center">
            <span class="c-grid-form__label required">厂商</span>
            <schema-select
              v-model="receivingCard.manufacturerKey"
              placeholder="请选择厂商"
              :schema="manufacturerSelectSchema"
            />
            <span class="c-grid-form__label required">设备型号</span>
            <el-input
              v-model.trim="receivingCard.screen"
              placeholder="最多50个字符"
              maxlength="50"
              clearable
            />
            <span class="c-grid-form__label">特性</span>
            <div class="l-flex--row c-grid-form__option">
              <span class="c-sibling-item">异步盒</span>
              <el-switch
                v-model="receivingCard.async"
                class="c-sibling-item"
                active-color="#13ce66"
                inactive-color="#ff4949"
              />
              <span class="c-sibling-item far">温度监测</span>
              <el-switch
                v-model="receivingCard.temperature"
                class="c-sibling-item"
                active-color="#13ce66"
                inactive-color="#ff4949"
              />
              <span class="c-sibling-item far">电压监测</span>
              <el-switch
                v-model="receivingCard.voltage"
                class="c-sibling-item"
                active-color="#13ce66"
                inactive-color="#ff4949"
              />
            </div>
            <span class="c-grid-form__label required">设备IP</span>
            <el-input
              v-model.trim="receivingCard.ip"
              placeholder="192.168.0.1"
              maxlength="15"
              clearable
            />
          </div>
        </confirm-dialog>
        <el-dialog
          class="c-progress"
          :visible.sync="showProgress"
          width="50%"
          :close-on-click-modal="false"
          :close-on-press-escape="false"
          :show-close="false"
        >
          <el-progress
            :percentage="progress"
            :stroke-width="24"
            text-inside
            status="success"
          />
        </el-dialog>
      </template>
    </template>
  </div>
</template>

<script>
import {
  getReceivingCardManufacturers,
  getReceivingCard,
  addReceivingCard,
  updateReceivingCard
} from '@/api/external'
import { validIPv4 } from '@/utils/validate'
import ReceivingCardTopology from './ReceivingCardTopology'

export default {
  name: 'ReceivingCard',
  components: {
    ReceivingCardTopology
  },
  props: {
    device: {
      type: Object,
      required: true
    }
  },
  data () {
    return {
      manufacturerSelectSchema: {
        remote: getReceivingCardManufacturers,
        value: 'manufacturerKey',
        label: 'manufacturerName'
      },
      loading: false,
      error: false,
      info: null,
      receivingCard: {},
      showProgress: false,
      progress: 0,
      showTopology: false
    }
  },
  created () {
    this.getDefaults()
  },
  methods: {
    getDefaults () {
      if (this.loading) {
        return
      }
      this.info = null
      this.loading = true
      this.error = false
      getReceivingCard(this.device.id).then(
        ({ data }) => {
          if (data) {
            const info = {
              manufacturerKey: data.manufacturerKey,
              screen: data.screen,
              async: data.async,
              temperature: data.temperature,
              voltage: data.voltage,
              topology: JSON.parse(data.topology),
              ip: data.ip
            }
            this.info = { ...info }
            this.$defaultInfo = { ...info }
            this.manufacturerSelectSchema.option = { value: data.manufacturerKey, label: data.manufacturerName }
          }
        },
        () => {
          this.error = true
        }
      ).finally(() => {
        this.loading = false
      })
    },
    onBind () {
      this.receivingCard = {
        manufacturerKey: '',
        topologyFile: null,
        screen: '',
        async: false,
        temperature: false,
        voltage: false,
        ip: ''
      }
      this.$refs.addDialog.show()
    },
    onError (message) {
      this.$message({
        type: 'warning',
        message
      })
      return false
    },
    checkProp (target, key) {
      const val = target[key]
      switch (key) {
        case 'manufacturerKey':
          if (!val) {
            return this.onError('请选择厂商')
          }
          break
        case 'topologyFile':
          if (!val) {
            return this.onError('请选择拓扑结构文件')
          }
          break
        case 'screen':
          if (!val) {
            return this.onError('请填写设备型号')
          }
          break
        case 'ip':
          if (!val) {
            return this.onError('请填写设备IP')
          }
          if (!validIPv4(val)) {
            return this.onError('设备IP格式错误')
          }
          break
        default:
          break
      }
      return true
    },
    onChange ({ raw }) {
      this.$refs.uploadTopology.clearFiles()
      this.receivingCard.topologyFile = raw
    },
    onSave (done) {
      if (!this.checkProp(this.receivingCard, 'manufacturerKey')) {
        return
      }
      if (!this.checkProp(this.receivingCard, 'topologyFile')) {
        return
      }
      if (!this.checkProp(this.receivingCard, 'screen')) {
        return
      }
      if (!this.checkProp(this.receivingCard, 'ip')) {
        return
      }
      const formData = new FormData()
      formData.append('deviceId', this.$route.params.id)
      formData.append('manufacturerKey', this.receivingCard.manufacturerKey)
      formData.append('topologyFile', this.receivingCard.topologyFile)
      formData.append('screen', this.receivingCard.screen)
      formData.append('temperature', this.receivingCard.temperature)
      formData.append('voltage', this.receivingCard.voltage)
      formData.append('async', this.receivingCard.async)
      formData.append('ip', this.receivingCard.ip)
      this.progress = 0
      this.showProgress = true
      addReceivingCard(formData, ({ loaded, total }) => {
        this.progress = Math.min(99, loaded * 100 / total | 0)
      }).finally(() => {
        this.progress = 100
        this.showProgress = false
      }).then(() => {
        done()
        this.getDefaults()
      })
    },
    onChangeTopology ({ raw }) {
      this.$refs.upload.clearFiles()
      this.progress = 0
      this.showProgress = true
      this.updateProp('topologyFile', raw, ({ loaded, total }) => {
        this.progress = Math.min(99, loaded * 100 / total | 0)
      }).finally(() => {
        this.progress = 100
        this.showProgress = false
      }).then(() => {
        this.getDefaults()
      })
    },
    onChangeProp (key) {
      if (this.info[key] === this.$defaultInfo[key]) {
        return
      }
      if (!this.checkProp(this.info, key)) {
        this.info[key] = this.$defaultInfo[key]
        return
      }
      this.updateProp(key, this.info[key]).then(
        () => {
          this.$defaultInfo[key] = this.info[key]
        },
        () => {
          this.info[key] = this.$defaultInfo[key]
        }
      )
    },
    updateProp (key, data, options) {
      const formData = new FormData()
      formData.append('deviceId', this.device.id)
      formData.append(key, data)
      return updateReceivingCard(formData, options)
    },
    onView () {
      this.showTopology = true
    }
  }
}
</script>

<style lang="scss" scoped>
.c-card-grid {
  display: grid;
  overflow: auto;

  &.empty {
    position: relative;
    background: url("~@/assets/screen.png") 0 0 / 96px 96px repeat;

    &::after {
      content: "未录入";
      display: inline-flex;
      justify-content: center;
      align-items: center;
      position: absolute;
      top: 50%;
      left: 50%;
      width: 200px;
      height: 64px;
      color: #fff;
      font-size: 18px;
      letter-spacing: 6px;
      background-color: rgba($info--dark, 0.8);
      transform: translate(-50%, -50%);
    }
  }
}

.o-receiving-card {
  position: relative;
  display: inline-flex;
  justify-content: center;
  align-items: center;
  color: $info;
  background: url("~@/assets/screen.png") 0 0 / 100% 100% no-repeat;

  &.normal,
  &.error {
    color: $success--dark;
  }

  &::after {
    content: attr(status);
    position: absolute;
    top: 0;
    right: 0;
    width: 40px;
    padding: 4px 0;
    color: #fff;
    font-size: 12px;
    line-height: 1;
    text-align: center;
    background-color: $info;
    transform-origin: top right;
    transform: scale(0.8);
  }

  &.normal::after {
    background-color: $black;
  }

  &.error::after {
    background-color: $error;
  }

  &__status {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    width: 36px;
    height: 36px;
    padding-bottom: 4px;
    color: $black;
    font-size: 14px;
    font-weight: bold;
    background: url("~@/assets/icon_card_unknown.png") 0 0 / 100% 100% no-repeat;
  }

  &.normal {
    .o-receiving-card__status {
      color: $error;
      background-image: url("~@/assets/icon_card_normal.png");
    }
  }

  &.error {
    .o-receiving-card__status {
      background-image: url("~@/assets/icon_card_abnormal.png");
    }
  }

  &__arrow {
    position: absolute;
    z-index: 1;

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

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

    &.bottom {
      transform: rotate(180deg);
    }

    &::before {
      content: "";
      position: absolute;
      left: 50%;
      bottom: 20px;
      width: 6px;
      height: 46px;
      background-color: currentColor;
      transform: translateX(-50%);
    }

    &::after {
      content: "";
      position: absolute;
      left: 50%;
      bottom: 66px;
      border-left: 10px solid transparent;
      border-right: 10px solid transparent;
      border-bottom: 10px solid currentColor;
      transform: translateX(-50%);
    }
  }
}
</style>
