<template>
  <div
    ref="wrapper"
    v-loading="!loaded && loading"
    element-loading-background="transparent"
  >
    <warning
      v-if="!loaded && !loading"
      @click="getBoundThirdPartyDevices"
    />
    <div
      v-if="loaded"
      class="c-link-state l-flex--row"
      :class="className"
    >
      <div
        class="c-link-state__main"
        :style="styles"
      >
        <div
          v-for="item in items"
          :key="item.key"
          class="o-link-item"
          :class="item.className"
          @click="onClick(item)"
        >
          <div class="o-link-item__name">{{ item.label }}</div>
          <device-player
            v-if="item.key === 'led'"
            :device="device"
            autoplay
            retry
          />
          <svg-icon
            v-else
            class="o-link-item__img"
            :icon-class="item.icon"
          />
        </div>
        <div
          v-for="line in lines"
          :key="line.key"
          class="o-line"
          :class="line.className"
        />
      </div>
    </div>
    <slot />
  </div>
</template>

<script>
import { getBoundThirdPartyDevices } from '@/api/external'
import { ThirdPartyDevice } from '@/constant'

const LinkItems = Object.freeze([
  {
    key: 'msr',
    label: '浪潮屏媒安播云平台'
  },
  {
    key: 'device',
    label: '浪潮超高清媒体播控器'
  },
  {
    key: 'led',
    label: 'LED大屏'
  },
  {
    key: ThirdPartyDevice.GATEWAY,
    alias: 'gateway',
    label: '浪潮物联网关',
    iconKey: 'gateway',
    canClick: true
  },
  {
    key: ThirdPartyDevice.TRAFFIC_CAMERA,
    alias: 'traffic_camera',
    label: '人流量监测摄像头',
    iconKey: 'camera',
    canClick: true
  },
  {
    key: ThirdPartyDevice.LED_CAMERA,
    alias: 'led_camera',
    label: 'LED屏监测摄像头',
    iconKey: 'camera',
    canClick: true
  },
  {
    key: ThirdPartyDevice.SENDING_CARD,
    alias: 'sending_card',
    label: '发送控制设备',
    iconKey: 'sending-card',
    canClick: true
  },
  {
    key: ThirdPartyDevice.RECEIVING_CARD,
    alias: 'receiving_card',
    label: '接收卡',
    iconKey: 'receiving-card',
    canClick: true
  }
])

const LineFromeTo = {
  1: ['msr', 'device'],
  2: ['device', ThirdPartyDevice.SENDING_CARD],
  3: [ThirdPartyDevice.SENDING_CARD, ThirdPartyDevice.RECEIVING_CARD],
  4: [ThirdPartyDevice.RECEIVING_CARD, 'led'],
  5: ['msr', ThirdPartyDevice.GATEWAY],
  6: ['msr', ThirdPartyDevice.LED_CAMERA, ThirdPartyDevice.TRAFFIC_CAMERA],
  7: ['msr', ThirdPartyDevice.LED_CAMERA],
  8: ['msr', ThirdPartyDevice.LED_CAMERA],
  9: ['msr', ThirdPartyDevice.TRAFFIC_CAMERA],
  10: [ThirdPartyDevice.GATEWAY, 'led'],
  11: ['msr', ThirdPartyDevice.GATEWAY, ThirdPartyDevice.LED_CAMERA, ThirdPartyDevice.TRAFFIC_CAMERA]
}

export default {
  name: 'FullLink',
  props: {
    device: {
      type: Object,
      required: true
    },
    online: {
      type: [Boolean, String],
      default: false
    },
    theme: {
      type: String,
      default: 'dark'
    },
    square: {
      type: [Boolean, String],
      default: false
    }
  },
  data () {
    return {
      linkDeviceMap: null,
      scale: 1,
      loading: false,
      loaded: false
    }
  },
  computed: {
    targetId () {
      return this.device.id
    },
    className () {
      return [this.theme, this.square ? 'square' : ''].join(' ')
    },
    linkState () {
      const map = {
        msr: 1,
        device: this.online ? 1 : 0,
        led: this.online ? 1 : 0,
        [ThirdPartyDevice.GATEWAY]: -1,
        [ThirdPartyDevice.LED_CAMERA]: -1,
        [ThirdPartyDevice.TRAFFIC_CAMERA]: -1,
        [ThirdPartyDevice.SENDING_CARD]: -1,
        [ThirdPartyDevice.RECEIVING_CARD]: -1
      }
      if (this.linkDeviceMap) {
        for (const item of this.linkDeviceMap) {
          map[item.deviceType] = item.status
        }
      }
      return map
    },
    items () {
      const map = this.linkState
      return LinkItems.map(({ key, alias, label, iconKey, canClick }) => {
        const status = map[key]
        return {
          key, label, status, canClick,
          icon: status === -1
            ? 'link-unbound'
            : `link-${iconKey || key}-${status === 1 ? 'online' : 'offline'}`,
          className: [alias || key, canClick && status === 1 ? 'u-pointer' : ''].join(' ')
        }
      })
    },
    lines () {
      const state = this.linkState
      return Object.keys(LineFromeTo).map(key => {
        const from = LineFromeTo[key][0]
        const to = LineFromeTo[key].slice(1)
        return {
          key: `line${key}`,
          className: [`l${key}`, state[from] === 1 && to.some(key => state[key] === 1) ? 'linked' : ''].join(' ')
        }
      })
    },
    styles () {
      return {
        transform: `scale(${this.scale})`
      }
    }
  },
  created () {
    this.getBoundThirdPartyDevices()
    this.$timer = setInterval(this.getBoundThirdPartyDevices, 10000)
  },
  mounted () {
    this.checkScale()
    window.addEventListener('resize', this.checkScale)
  },
  beforeDestroy () {
    window.removeEventListener('resize', this.checkScale)
    clearInterval(this.$timer)
  },
  methods: {
    checkScale () {
      const elm = this.$refs.wrapper
      const width = elm.clientWidth
      const height = elm.clientHeight
      this.scale = this.square
        ? Math.min(width / 804, height / 640).toFixed(2)
        : Math.min(width / 966, height / 420).toFixed(2)
    },
    getBoundThirdPartyDevices () {
      if (this.loading) {
        return
      }
      this.loading = true
      getBoundThirdPartyDevices(this.targetId, true).then(({ data }) => {
        this.linkDeviceMap = data
        this.loaded = true
      }).finally(() => {
        this.loading = false
      })
    },
    onClick (item) {
      if (!item.canClick) {
        return
      }
      this.$emit('click', item)
    }
  }
}
</script>

<style lang="scss" scoped>
@mixin getPosition($left, $top, $width, $height) {
  top: $top;
  left: $left;
  width: $width;
  height: $height;
}

.c-link-state {
  width: 100%;
  height: 100%;
  overflow: hidden;

  &__main {
    position: relative;
    width: 966px;
    height: 420px;
    transform-origin: left center;
  }

  &.dark {
    color: $black;
  }

  &.light {
    color: #fff;
  }

  &.square {
    .c-link-state__main {
      width: 804px;
      height: 640px;
    }

    .o-link-item {
      &.msr {
        top: 0;
        left: 0;
      }

      &.device {
        top: 75px;
        left: 286px;
      }

      &.sending_card {
        top: 75px;
        left: 472px;
      }

      &.receiving_card {
        top: 75px;
        left: 660px;
      }

      &.gateway {
        top: 432px;
        left: 52px;
        width: 138px;
        height: 138px;
      }

      &.traffic_camera {
        top: 280px;
        left: 460px;
      }

      &.led_camera {
        top: 400px;
        left: 290px;
      }

      &.led {
        top: 400px;
        left: 440px;
      }
    }

    .o-line {
      &.l1 {
        top: 166px;
        left: 232px;
        width: 60px;
        transform: none;
      }

      &.l2 {
        top: 166px;
        left: 418px;
        width: 60px;
      }

      &.l3 {
        top: 166px;
        left: 604px;
        width: 60px;
      }

      &.l4 {
        top: 202px;
        left: 728px;
        width: 198px;
      }

      &.l5 {
        top: 334px;
        left: 122px;
        width: 108px;
        transform: rotate(90deg);
      }

      &.l6 {
        top: 334px;
        left: 122px;
        width: 120px;
      }

      &.l7 {
        top: 334px;
        left: 240px;
        width: 120px;
      }

      &.l8 {
        top: 454px;
        left: 240px;
      }

      &.l9 {
        top: 334px;
        left: 240px;
        width: 234px;
      }

      &.l10 {
        top: 522px;
        left: 184px;
        width: 256px;
      }

      &.l11 {
        top: 230px;
        left: 122px;
        width: 104px;
        height: 2px;
        transform: rotate(90deg);
        transform-origin: left;
      }
    }
  }
}

@keyframes move {
  from {
    background-position: 0 0;
  }
  to {
    background-position: 3em 0;
  }
}

.o-link-item {
  position: absolute;
  z-index: 1;

  &__name {
    position: absolute;
    top: 100%;
    left: 50%;
    font-size: 14px;
    line-height: 1;
    white-space: nowrap;
    transform: translateX(-50%);
  }

  &__img {
    width: 100%;
    height: 100%;
  }

  &.msr {
    @include getPosition(0, 42px, 242px, 236px);
  }

  &.device {
    @include getPosition(270px, 0, 138px, 138px);
  }

  &.sending_card {
    @include getPosition(484px, 0, 138px, 138px);
  }

  &.receiving_card {
    @include getPosition(720px, 0, 138px, 138px);

    .o-link-item__name {
      transform: translateX(8px);
    }
  }

  &.gateway {
    @include getPosition(270px, 250px, 138px, 138px);
  }

  &.traffic_camera {
    @include getPosition(480px, 156px, 80px, 80px);
  }

  &.led_camera {
    @include getPosition(480px, 252px, 80px, 80px);
  }

  &.led {
    @include getPosition(604px, 208px, 352px, 198px);

    .o-link-item__name {
      top: -8px;
      left: auto;
      right: 0;
      bottom: auto;
      transform: translateY(-100%);
    }
  }
}

.o-line {
  position: absolute;
  background-color: $border;

  &.linked {
    background-size: 3em 1em;
    background-image: linear-gradient(
      -90deg,
      transparent 0em,
      transparent 1em,
      #026af2 1em,
      #026af2 2em,
      transparent 3em
    );
    animation: move 0.6s linear infinite;
  }

  &.l1 {
    transform: skewY(-30deg);
    transform-origin: left;
    @include getPosition(180px, 178px, 122px, 2px);
  }

  &.l2 {
    @include getPosition(402px, 92px, 86px, 2px);
  }

  &.l3 {
    @include getPosition(618px, 92px, 106px, 2px);
  }

  &.l4 {
    transform: rotate(90deg);
    transform-origin: left;
    @include getPosition(788px, 129px, 80px, 2px);
  }

  &.l5 {
    transform: skewY(30deg);
    transform-origin: left;
    @include getPosition(170px, 244px, 122px, 2px);
  }

  &.l6 {
    @include getPosition(234px, 209px, 196px, 2px);
  }

  &.l7 {
    transform: rotate(90deg);
    transform-origin: left;
    @include getPosition(428px, 209px, 95px, 2px);
  }

  &.l8 {
    @include getPosition(428px, 304px, 66px, 2px);
  }

  &.l9 {
    @include getPosition(428px, 209px, 66px, 2px);
  }

  &.l10 {
    @include getPosition(376px, 356px, 228px, 2px);
  }
}
</style>
