<template>
  <div class="l-flex--col center has-border radius has-padding">
    <i
      class="o-icon lg u-pointer"
      @click="invoke"
    />
    <div class="has-padding u-color--black u-bold">网络设置</div>
    <confirm-dialog
      ref="networkDialog"
      title="网络设置"
      @confirm="onSave"
    >
      <!-- <tabbar
        :items="tabs"
        :active.sync="active"
      /> -->
      <wired
        key="wired"
        class="u-align-self--center"
        :eth.sync="eth"
        :eths="eths"
      />
      <!-- <wireless
        v-if="isWireless"
        key="wireless"
        class="u-align-self--center"
        :wireless="wireless"
      /> -->
    </confirm-dialog>
  </div>
</template>

<script>
import {
  subscribe,
  unsubscribe
} from '@/utils/mqtt'
import {
  validIPv4,
  validIPv6
} from '@/utils/validate'
import { saveBoxLogger } from '@/api/platform'
import baseMixin from '../mixins/base'
import Wired from './Wired'
// import Wireless from './Wireless'

export default {
  name: 'DeviceNetwork',
  components: {
    Wired
    // Wired,
    // Wireless
  },
  mixins: [baseMixin],
  data () {
    return {
      tabs: [
        { key: 'wired', name: '有线网络' },
        { key: 'wireless', name: '无线网络' }
      ],
      active: null,
      eth: '0',
      eths: null,
      wireless: null
    }
  },
  computed: {
    isWired () {
      return this.active === 'wired'
    },
    wired () {
      return this.eths?.[this.eth]
    },
    isWireless () {
      return this.active === 'wireless'
    },
    replyTopic () {
      return `${this.device.productId}/${this.device.id}/function/invoke/reply`
    }
  },
  created () {
    subscribe([this.replyTopic], this.onMessage)
  },
  beforeDestroy () {
    unsubscribe([this.replyTopic], this.onMessage)
  },
  methods: {
    onMessage (topic, message) {
      if (!this.$messageId || topic !== this.replyTopic) {
        return
      }
      message = JSON.parse(message)
      if (message.messageId === this.$messageId) {
        this.closeAsyncLoading()
        try {
          const eths = JSON.parse(message.output)
          if (eths?.length) {
            this.showNetwork(eths)
            return
          }
        } catch (e) {
          console.log(e)
        }
        this.$message({
          type: 'warning',
          message: '未发现设备网口，请稍后重试'
        })
      }
    },
    invoke () {
      this.sendTopic(
        'network',
        [],
        '未获取到设备网络状态，请稍后重试'
      )
    },
    showNetwork (eths) {
      this.active = 'wired'
      this.eth = '0'
      this.eths = eths.map(eth => this.createEth(eth))
      this.wireless = {
        enable: true,
        name: '',
        password: '',
        auto: false
      }
      this.$refs.networkDialog.show()
    },
    createEth (eth) {
      const { name, setting, address, subnetMask, defaultGateway, preferredDNS, alternativeDNS } = eth
      return {
        name,
        mode: setting === 'manual' ? 'manual' : 'dhcp',
        ip4: {
          enable: true,
          address: address || '',
          mask: subnetMask || '',
          gateway: defaultGateway || '',
          dns1: preferredDNS || '',
          dns2: alternativeDNS || ''
        },
        ip6: this.createIPv6Setting()
      }
    },
    createIPv6Setting () {
      return {
        enable: false,
        address: '',
        mask: 32,
        gateway: '',
        dns1: '',
        dns2: ''
      }
    },
    onSave (done) {
      this.isWired && this.onWired(done)
      this.isWireless && this.onWireless(done)
    },
    onWired (done) {
      if (!this.validWired()) {
        return
      }
      const { name, mode, ip4, ip6 } = this.wired
      const inputs = []
      if (mode === 'dhcp') {
        inputs.push({
          name,
          value: JSON.stringify({ setting: mode })
        })
        // inputs.push({
        //   name: `${name}-ipv6`,
        //   value: JSON.stringify({ setting: mode })
        // })
      } else {
        if (ip4.enable) {
          const { address, mask, gateway, dns1, dns2 } = ip4
          inputs.push({
            name,
            value: JSON.stringify({
              setting: mode,
              address,
              subnetMask: mask,
              defaultGateway: gateway,
              preferredDNS: dns1,
              alternativeDNS: dns2
            })
          })
        }
        if (ip6.enable) {
          const { address, mask, gateway, dns1, dns2 } = ip6
          inputs.push({
            name: `${name}-ipv6`,
            value: JSON.stringify({
              name,
              setting: mode,
              address,
              subnetPrefixLegth: mask,
              defaultGateway: gateway,
              preferredDNS: dns1,
              alternativeDNS: dns2
            })
          })
        }
      }
      this.$confirm(
        `将${name}有线网络设置为配置内容？`,
        { type: 'warning' }
      ).then(() => {
        done()
        this.sendTopic('wiredNetwork', inputs).then(() => {
          saveBoxLogger({
            description: `将设备【${this.device.name}】的IP模式设为${mode === 'dhcp' ? 'DHCP' : '静态IP'}`,
            method: '网络设置',
            params: JSON.stringify({
              id: this.deviceId,
              name: this.device.name,
              ...inputs
            })
          })
        })
      })
    },
    onWireless (done) {
      if (!this.validWireless()) {
        return
      }
      const inputs = []
      const { enable, name, password, auto } = this.wireless
      if (enable) {
        inputs.push({
          name: 'wirelessFidelity',
          value: {
            status: 1,
            name,
            password,
            auto: auto ? 1 : 0
          }
        })
      } else {
        inputs.push({
          name: 'wirelessFidelity',
          value: JSON.stringify({ status: -1 })
        })
      }
      this.$confirm(
        '将无线网络设置为配置内容？',
        { type: 'warning' }
      ).then(() => {
        done()
        this.sendTopic('wirelessFidelity', inputs)
      })
    },
    onError (message) {
      this.$message({
        type: 'warning',
        message
      })
      return false
    },
    validWired () {
      if (this.wired.mode === 'manual') {
        const { ip4, ip6 } = this.wired
        if (!ip4.enable && !ip6.enable) {
          return this.onError('请配置IPv4或IPv6')
        }
        if (ip4.enable && !this.validIPv4(ip4)) {
          return false
        }
        if (ip6.enable && !this.validIPv6(ip6)) {
          return false
        }
      }
      return true
    },
    validIPv4 (ip4) {
      const { address, mask, gateway, dns1, dns2 } = ip4
      const type = 'IPv4'
      if (!this.isValid(address, validIPv4, type, 'IP地址')) {
        return false
      }
      if (!this.isValid(mask, validIPv4, type, '子网掩码')) {
        return false
      }
      if (!this.isValid(gateway, validIPv4, type, '网关')) {
        return false
      }
      if (dns1 && !validIPv4(dns1)) {
        return this.onError('IPv4的主DNS格式错误')
      }
      if (dns2 && !validIPv4(dns2)) {
        return this.onError('IPv4的备DNS格式错误')
      }
      return true
    },
    validIPv6 (ip6) {
      const { address, gateway, dns1, dns2 } = ip6
      const type = 'IPv6'
      if (!this.isValid(address, validIPv6, type, 'IP地址')) {
        return false
      }
      if (gateway && !validIPv6(gateway)) {
        return this.onError('IPv6的网关格式错误')
      }
      if (dns1 && !validIPv6(dns1)) {
        return this.onError('IPv6的主DNS格式错误')
      }
      if (dns2 && !validIPv6(dns2)) {
        return this.onError('IPv6的备DNS格式错误')
      }
      return true
    },
    isValid (val, validate, type, name) {
      if (!val) {
        return this.onError(`请输入${type}的${name}`)
      }
      if (!validate(val)) {
        return this.onError(`${type}的${name}格式错误`)
      }
      return true
    },
    validWireless () {
      if (this.wireless.enable) {
        const { name, password } = this.wireless
        if (!name) {
          return this.onError('请输入网络名称')
        }
        if (!password) {
          return this.onError('请输入密码')
        }
      }
      return true
    }
  }
}
</script>

<style lang="scss" scoped>
.o-icon {
  background-image: url("~@/assets/icon_screen_network.png");
}
</style>
