<template>
  <wrapper
    fill
    margin
  >
    <div class="l-flex__none l-flex--row c-sibling-item--v c-count">
      <div
        class="l-flex__none c-count__title u-color--black u-bold u-ellipsis"
        :class="{ 'has-active u-pointer': multi }"
        @click="onChooseDepartment"
      >
        <i
          v-if="loading"
          class="el-icon-loading"
        />
        {{ group.name }}
      </div>
      <div class="l-flex__none c-count__item u-color--black u-bold u-text--center">
        <div>总数</div>
        <i
          v-if="monitor.loading"
          class="el-icon-loading"
        />
        <div v-else>{{ monitor.total }}</div>
      </div>
      <div class="l-flex__none c-count__item u-color--success dark u-bold u-text--center">
        <div>● 在线</div>
        <i
          v-if="monitor.loading"
          class="el-icon-loading"
        />
        <div v-else>{{ monitor.online }}</div>
      </div>
      <div class="l-flex__none c-count__item u-color--error dark u-bold u-text--center">
        <div>● 离线</div>
        <i
          v-if="monitor.loading"
          class="el-icon-loading"
        />
        <div v-else>{{ monitor.offline }}</div>
      </div>
      <div class="l-flex__none c-count__item u-color--info u-bold u-text--center">
        <div>● 未启用</div>
        <i
          v-if="monitor.loading"
          class="el-icon-loading"
        />
        <div v-else>{{ monitor.inactive }}</div>
      </div>
      <i
        class="el-icon-refresh o-icon md u-color--blue has-active u-pointer"
        @click="onRefresh"
      />
    </div>
    <div
      v-if="__PLACEHOLDER__"
      class="l-flex__none c-sibling-item--v far c-cards"
    >
      <card
        class="c-cards__item"
        type="info"
        title="总次数"
        tip="100"
      />
      <card
        class="c-cards__item"
        type="safety"
        title="安全异常"
        desc="累计异常数：30"
      />
      <card
        class="c-cards__item"
        type="performance"
        title="性能异常"
        desc="累计异常数：30"
        count="3"
      />
      <card
        class="c-cards__item"
        type="log"
        title="日志异常"
        desc="累计异常数：30"
        count="10"
      />
      <card
        class="c-cards__item"
        type="date"
        title="即将空闲排期"
        count="100"
      />
    </div>
    <div class="l-flex__auto l-grid--info c-sibling-item--v far u-overflow-y--auto">
      <device
        v-for="item in deviceOptions.list"
        :key="item.id"
        :device="item"
      />
    </div>
    <div
      v-if="!deviceOptions.loaded"
      class="c-sibling-item--v far u-text--center"
    >
      <i class="el-icon-loading" />
    </div>
    <el-drawer
      title="个人设置"
      :visible.sync="drawer"
      direction="ltr"
      :size="480"
      :with-header="false"
      append-to-body
    >
      <department-tree
        class="c-department-tree"
        :tree-data="groups"
        @change="onGroupChanged"
      />
    </el-drawer>
  </wrapper>
</template>

<script>
import { mapGetters } from 'vuex'
import {
  subscribe,
  unsubscribe
} from '@/utils/mqtt'
import { getDepartmentTree } from '@/api/user'
import {
  getDevicesByAdmin,
  getDeviceStatisticsByCustom
} from '@/api/device'
import Card from './components/Card'
import Device from './components/Device'

export default {
  name: 'Dashboard',
  components: {
    Card,
    Device
  },
  data () {
    return {
      monitor: { loading: true },
      deviceOptions: {
        list: [],
        loaded: false
      },
      loading: true,
      loaded: false,
      multi: true,
      drawer: false,
      groups: null,
      group: null
    }
  },
  computed: {
    ...mapGetters(['tenant', 'org'])
  },
  created () {
    this.$timer = -1
    subscribe([
      '+/+/online',
      '+/+/offline',
      '+/+/calendar/update'
    ], this.onMessage)
    this.getDepartmentTree()
    this.group = { path: this.org, name: '我的部门' }
    this.refreshDevices(true)
  },
  beforeDestroy () {
    clearTimeout(this.$timer)
    this.monitor = { loading: true }
    unsubscribe([
      '+/+/online',
      '+/+/offline',
      '+/+/calendar/update'
    ], this.onMessage)
  },
  methods: {
    getDepartmentTree (isClick) {
      this.loading = true
      getDepartmentTree().finally(() => {
        this.loading = false
      }).then(({ data }) => {
        this.loaded = true
        if (data[0]?.children?.length) {
          this.groups = data
          if (isClick) {
            this.drawer = true
          }
        } else {
          this.multi = false
        }
      })
    },
    onGroupChanged ({ path, name }) {
      if (this.group.path !== path) {
        this.group = { path, name }
        this.refreshDevices(true)
        this.drawer = false
      }
    },
    onMessage (topic) {
      if (!this.deviceOptions.loaded) {
        return
      }
      const result = /^\d+\/(\d+)\/(online|offline)$/.exec(topic)
      if (!result) {
        return
      }
      const deviceId = result[1]
      const status = result[2]
      const device = this.deviceOptions.list.find(({ id }) => id === deviceId)
      if (device) {
        const onlineStatus = device.onlineStatus === 1 ? 'online' : 'offline'
        if (status === onlineStatus) {
          return
        }
        this.refreshDevices()
      }
    },
    onRefresh () {
      this.refreshDevices()
    },
    refreshDevices (force) {
      if (!force && this.monitor.loading) {
        return
      }
      const monitor = {
        loading: true,
        total: '-',
        online: '-',
        offline: '-',
        inactive: '-'
      }
      this.monitor = monitor
      clearTimeout(this.$timer)
      this.deviceOptions = { loaded: false }
      getDeviceStatisticsByCustom(
        this.group.path === this.tenant
          ? { tenant: this.group.path }
          : { org: this.group.path }
      ).then(({ data }) => {
        const { deactivatedTotal, notConnectedTotal, offLineTotal, onLineTotal, total } = data
        monitor.total = total
        monitor.online = onLineTotal
        monitor.offline = offLineTotal + notConnectedTotal
        monitor.inactive = deactivatedTotal
      }).finally(() => {
        monitor.loading = false
        if (!this.monitor.loading) {
          this.getDevices(this.monitor.total - this.monitor.inactive)
        }
      })
    },
    sort (a, b) {
      if (a.onlineStatus === b.onlineStatus) {
        return a.createTime <= b.createTime ? 1 : -1
      }
      return a.onlineStatus === 1 ? -1 : 1
    },
    getDevices (total) {
      if (!total || total === '-') {
        this.deviceOptions = { list: [], loaded: true }
        return
      }
      const options = { list: [], loaded: false }
      this.deviceOptions = options
      const query = {
        pageNum: 1,
        pageSize: total,
        activate: 1
      }
      if (this.group.path === this.tenant) {
        query.tenant = this.group.path
      } else {
        query.org = this.group.path
      }
      getDevicesByAdmin(query, { custom: true }).then(
        ({ data }) => {
          options.list = data.sort(this.sort)
          options.loaded = true
        },
        ({ isCancel }) => {
          if (!isCancel && !this.monitor.loading) {
            this.$timer = setTimeout(total => {
              this.getDevices(total)
            }, 2000, total)
          }
        }
      )
    },
    onChooseDepartment () {
      if (this.loaded) {
        if (this.multi) {
          this.drawer = true
        }
      } else if (!this.loading) {
        this.getDepartmentTree(true)
      }
    }
  }
}
</script>

<style lang="scss" scoped>
.c-department-tree {
  height: 100%;
  padding: $spacing--xs;
}

.c-count {
  justify-content: space-between;
  padding: $spacing--xs $spacing;
  border-radius: $radius;
  background-color: #fff;

  &__title {
    max-width: 200px;
  }

  &__item > div:first-child {
    margin-bottom: 10px;
  }
}

.c-cards {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-column-gap: $spacing;

  &__item {
    min-width: 0;
  }
}
</style>
