<style>
.info-div {
  width: 100%;
  position: absolute;
  bottom: 0;
  left: 0;
}
</style>
<template>
  <v-app>
    <v-app-bar
      app
      color="primary"
      dark
      dense
    >
      <v-app-bar-nav-icon>
        <v-avatar size="20">
          <img
            src="/favicon.ico"
            alt="veypi"
          >
        </v-avatar>
      </v-app-bar-nav-icon>
      <v-toolbar-title>
        {{ $store.state.algorithms[$store.state.algorithm].text }}
      </v-toolbar-title>
      <v-spacer></v-spacer>
      <v-text-field
        v-model="search"
        append-icon="mdi-magnify"
        label="Search"
        single-line
        hide-details
      ></v-text-field>
      <v-icon class="mr-5" @click="info=!info">mdi-information</v-icon>
      <v-icon class="mr-5" @click="sync">mdi-autorenew</v-icon>
      <v-btn color="warning" class="mr-5" v-if="$store.state.algorithm===0" @click="$refs.core.lay2()">计算</v-btn>
      <v-icon @click="dialog=!dialog">mdi-cog</v-icon>
    </v-app-bar>
    <v-main>
      <v-system-bar>
        <v-row class="text-center">
          <v-col>边数: {{ $store.state.edgesNum }}</v-col>
          <v-col>节点数: {{ $store.state.nodesNum }}</v-col>
        </v-row>
      </v-system-bar>
      <router-view ref="core" style="height: 100%;width: 100%"></router-view>
    </v-main>
    <div class="info-div" v-if="info">
      <v-data-table
        class="mx-auto"
        :headers="headers"
        :items="nodeList"
        :search="search"
        disable-sort
        dense
        height="300px"
        style="background: rgba(0,0,0,0.2);"
      >
        <template v-slot:item.x="{ item }">
        {{ item.x.toFixed(2) }}
        </template>
        <template v-slot:item.y="{ item }">
        {{ item.y.toFixed(2) }}
        </template>
        <template v-slot:item.act="{ item }">
        <v-btn v-if="item.color === freeC " color="warning" @click="lock(item)">固定</v-btn>
        <v-btn v-else color="primary" @click="unlock(item)">解除</v-btn>
        </template>
      </v-data-table>
    </div>
    <v-dialog
      v-model="dialog"
      transition="dialog-bottom-transition"
      max-width="600"
    >
      <v-card>
        <v-system-bar
          color="success"
          dark
        >
          设置
        </v-system-bar>
        <v-card-text class="mt-10">
          <v-form>
            <v-select v-model="$store.state.algorithm" :items="$store.state.algorithms" label="算法"></v-select>
            <v-slider
              label="节点数量"
              class="mt-10"
              v-model="$store.state.nodesNum"
              thumb-label="always"
              :max="$store.state.algorithm ? 100: 10"
              :min="5"
            ></v-slider>
            <v-slider
              :max="$store.state.nodesNum * 5"
              :min="$store.state.nodesNum * (1 + $store.state.algorithm) - 1" label="边数量" class="mt-10"
              v-model="$store.state.edgesNum" thumb-label="always"></v-slider>
          </v-form>
        </v-card-text>
      </v-card>
    </v-dialog>
  </v-app>
</template>

<script lang="ts">
import Vue from 'vue'

function uniform2NormalDistribution() {
  let sum = 0.0
  for (let i = 0; i < 12; i++) {
    sum = sum + Math.random(1)
  }
  return sum - 6.0
}

function getNumberInNormalDistribution(mean, stdDev) {
  return mean + (uniform2NormalDistribution() * stdDev)
}

export default Vue.extend({
  name: 'App',

  components: {},

  data: () => ({
    freeC: '#5cf43d',
    search: '',
    headers: [
      {
        text: '节点id',
        align: 'start',
        width: '60px',
        value: 'id'
      },
      {text: 'x', value: 'x', width: 60},
      {text: 'y', value: 'y', width: 60},
      {text: 'act', value: 'act'}
    ],
    dialog: false,
    info: false
    //
  }),
  computed: {
    nodeList() {
      return Object.keys(this.$store.state.nodes).map(v => {
        return this.$store.state.nodes[v]
      })
    }
  },
  methods: {
    lock(n) {
      n.color = 'red'
      n.fx = n.x
      n.fy = n.y
      const graph = this.$refs.core.graph
      graph.updateItem(n.id, {color: n.color})
    },
    unlock(n) {
      n.color = this.freeC
      n.fx = null
      n.fy = null
      this.$refs.core.graph.updateItem(n.id, {color: n.color})
    },
    sync() {
      const edges = {}
      const nodes = {}
      for (let i = 0; i < this.$store.state.nodesNum; i++) {
        nodes['n' + i] = {
          label: 'n' + i,
          id: 'n' + i,
          // 随机布局
          color: this.freeC,
          x: i * Math.random() * 100,
          y: i * Math.random() * 100,
          size: Math.floor(Math.random() * 20) + 5
        }
      }
      // nodes.n0.color = 'red'
      // nodes.n0.fx = 100
      // nodes.n0.fy = 175
      // nodes.n0.x = 100
      // nodes.n0.y = 175
      // nodes.n1.color = 'red'
      // nodes.n1.fx = 200
      // nodes.n1.fy = 225
      // nodes.n1.x = 200
      // nodes.n1.y = 225
      // edges['0-2'] = {
      //   id: '0-2',
      //   source: 'n0',
      //   target: 'n2',
      //   value: 1
      // }
      // edges['2-3'] = {
      //   id: '2-3',
      //   source: 'n2',
      //   target: 'n3',
      //   value: 1
      // }
      // edges['3-4'] = {
      //   id: '3-4',
      //   source: 'n3',
      //   target: 'n4',
      //   value: 1
      // }
      // edges['4-1'] = {
      //   id: '4-1',
      //   source: 'n4',
      //   target: 'n1',
      //   value: 1
      // }
      let iter = 1
      for (let i = 0; i < this.$store.state.nodesNum; i++) {
        if (Object.keys(edges).length >= this.$store.state.edgesNum) {
          this.$store.state.edges = edges
          this.$store.state.nodes = nodes
          this.$refs.core.loaddata()
          return
        }
        let j = i
        while (i === j) {
          j = Math.floor(Math.random() * this.$store.state.nodesNum)
        }
        let ni = i
        if (i > j) {
          ni = j
          j = i
        }
        const v = Math.abs(Math.floor(getNumberInNormalDistribution(4, 20)))
        edges[ni + '-' + j] = {
          id: ni + '-' + j,
          source: 'n' + ni,
          target: 'n' + j,
          value: v
        }
      }
      while (iter < 10) {
        iter = iter + 1
        for (let i = 0; i < this.$store.state.nodesNum; i++) {
          for (let j = i + 1; j < this.$store.state.nodesNum; j++) {
            // const v = Math.floor(Math.random() * 10)
            const v = Math.floor(getNumberInNormalDistribution(4, 20))
            if (v > 0) {
              const id = i + '-' + j
              edges[id] = {
                id: id,
                source: 'n' + i,
                target: 'n' + j,
                value: v
                // label: v
              }
              if (Object.keys(edges).length >= this.$store.state.edgesNum) {
                this.$store.state.edges = edges
                this.$store.state.nodes = nodes
                this.$refs.core.loaddata()
                return
              }
            }
          }
        }
      }
    }
  },
  mounted() {
    this.sync()
  }
})
</script>
