<template>
  <b-overlay :show="texts === undefined" class="h-100">
    <svg
      width="100%" height="100%"
      ref="svg" id="vis"
      :view-box.camel="viewBox"
    >
      <g id="cards">
        <foreignObject
          v-for="(node, i) in nodes" :key="i"
          width="500" height="300"
          :x="node.x" :y="node.y"
          :transform="`rotate(${node.rotate})`"
        >
          <node-view
            :node="texts[i]"
            mode="card"
          />
        </foreignObject>
      </g>
    </svg>
  </b-overlay>
</template>

<script>
import { mapGetters } from 'vuex'

import { select, randomUniform, zoom } from 'd3'
import {
  forceSimulation, forceCenter, forceCollide
} from 'd3-force'


import { NodeView } from '@/components/nodes'


export default {
  name: 'CardMap',

  components: {
    NodeView
  },

  data () {
    return {
      width: 100,
      height: 100,
      nodes: undefined,
      simulation: forceSimulation(),
      viewBox: null,
      texts: undefined
    }
  },

  computed: {
    ...mapGetters(['textsDepart'])
  },

  methods: {
    updateSize () {
      const { width, height } = this.$refs.svg.getBoundingClientRect()
      Object.assign(this.$data, { width, height })
    }
  },

  created () {
    this.$store.dispatch('INIT_LIBRARY_MAP').then(data => {
      this.texts = data
      this.nodes = data.map((node, i) => {
        return { x: i, rotate: randomUniform(-25, 25)() }
      })

      this.$nextTick(() => {
        this.updateSize()
        this.viewBox = `0 0 ${this.width} ${this.height}`
        const svg = select('#vis')
        const g = select('#cards')
        svg.call(zoom()
          .extent([[0, 0], [this.width, this.height]])
          .scaleExtent([-5, 8])
          .on('zoom', zoomed))

        function zoomed ({ transform }) {
          g.attr('transform', transform)
        }

        this.simulation
          .nodes(this.nodes)
          .force('collide', forceCollide(d => randomUniform(250, 350)()))
          .force('center', forceCenter(this.width * 0.5, this.height * 0.5))
          .alphaDecay([0.02])
      })
    })
  }
}
</script>

<style lang="scss" scoped>
foreignObject {
  transform-origin: 250, 150;
}
</style>
