<script setup lang="ts">

import { ref, onMounted } from 'vue'
import HeaderBlock from './HeaderBlock.vue';
import { Network, type Data } from 'vis-network'
import { getGraph, updateNode } from './client';
import type { Graph, GraphEdge, GraphNode } from './models';

const network = ref<HTMLElement>()

const graph = ref<Graph>({
  nodes: [],
  edges: []
})

const selectedNode = ref<GraphNode>({
  id: 0,
  label: "",
  name: "",
  text: "",
  applications: [],
  links: [],
})

let net = <Network>{}
let data = <Data>{}

const displayEdges = ref(0)
const allEdges = ref(0)
const onApplicationEdges = ref(true)

async function loadGraph() {
  graph.value = await getGraph()
  allEdges.value = graph.value.edges.length
  if (onApplicationEdges.value) {
    graph.value.edges = graph.value.edges.filter(function (edge: GraphEdge) { return edge.type !== 'application' })
  }
  graph.value.edges.map(function (edge: GraphEdge) {
    if (edge.type == 'application') {
      edge.color = '#cccccc'
    }
  })
  displayEdges.value = graph.value.edges.length
  data = {
    nodes: graph.value.nodes,
    edges: graph.value.edges.sort(function (a: GraphEdge, b: GraphEdge) {
      if (a.type == 'application') {
        return 1
      }
      if (b.type == 'application') {
        return -1
      }
      return 0
    })
  }
  net.setData(data)
  console.log(graph.value.edges)
}

onMounted(async () => {
  if (!network.value) return

  const options = {
    interaction: {
      selectable: true,
    },
    nodes: {
      color: {
        border: '#2B7CE9',           // Normal border color
        background: '#97C2FC',       // Normal background color
        highlight: {                 // Selection state
          border: '#960000',
          background: '#ff9494'
        },
        hover: {                     // Hover state
          border: '#2B7CE9',
          background: '#D2E5FF'
        }
      }
    },
  }
  net = new Network(network.value, data, options)
  net.on("click", function (params) {
    if (params.nodes.length > 0) {
      selectNode(graph.value.nodes[params.nodes[0]])
    } else if (params.edges.length > 0) {
      console.log("Clicked edge:", params.edges[0]);
    }
  });

  await loadGraph()
  selectNode(graph.value.nodes[0])
})

function selectNode(node: GraphNode) {
  console.log("Select node:", node.id)
  selectedNode.value = node
  const links = graph.value.edges.filter(function (it: GraphEdge) {
    return it.from == node.id
  }).map(function (it: GraphEdge): GraphNode {
    const id = it.to
    const linkNode = graph.value.nodes.filter(function (it: GraphNode) { return it.id == id })
    return linkNode[0]
  })

  selectedNode.value.links = links
  net.selectNodes([selectedNode.value.id])
}

async function updateSelectedNode() {
  console.log("Update node:", selectedNode.value)
  await updateNode(selectedNode.value)
  await loadGraph()
}

function nodeHeader(node: GraphNode): string {
  return "[" + node.label + "] - " + node.name
}
</script>

<template>
  <HeaderBlock>
    <div>
      Редактор сценариев
    </div>
  </HeaderBlock>

  <div ref="network" class="graph-container"></div>

  <div class="nodes-container">
    <h2>Точки</h2>
    <div>Всего точек: {{ graph.nodes.length }}</div>
    <div>
      Всего связей: {{ allEdges }}, показано: {{ displayEdges }}
      <div>
        Показать все связи:
        <label class="checkbox-green">
          <input type="checkbox" v-on:click="onApplicationEdges = !onApplicationEdges, loadGraph()">
          <span class="checkbox-green-switch" data-label-on="Вкл" data-label-off="Выкл"></span>
        </label>
      </div>
    </div>
    <hr class="hr">

    <div v-bind:key="node.id" v-for="node in graph.nodes">
      <div :class="[node.id == selectedNode.id ? 'selected-node' : '']" class="node-select-button"
        v-on:click="selectNode(node)">
        {{ nodeHeader(node) }}
        <span v-if="node.applications.length > 0">({{ node.applications.length }})</span>
      </div>
    </div>
  </div>

  <div class="edit-node-container">
    <h2>Редактирование точки</h2>
    <div>
      {{ nodeHeader(selectedNode) }}
    </div>
    <div>
      <textarea class="node-text-edit-field" rows="30" v-model="selectedNode.text"></textarea>
    </div>
    <div>
      <h3>Приложения: {{ selectedNode.applications.length }}</h3>
      <div v-bind:key="index" v-for="(application, index) in selectedNode.applications">
        <textarea class="node-text-edit-field" rows="5" v-model="application.name"></textarea>
      </div>
    </div>
    <div>
      <h3>Ссылки: {{ selectedNode.links.length }}</h3>
      <div v-bind:key="node.id" v-for="node in selectedNode.links">
        <div class="node-select-button" v-on:click="selectNode(node)">
          - {{ nodeHeader(node) }}
        </div>
      </div>
    </div>
    <div>
      <button class="node-edit-save-button" v-on:click="updateSelectedNode()">Сохранить</button>
    </div>
  </div>
</template>

<style scoped>
.graph-container {
  width: 100%;
  height: calc(100vh - 50px);
  border: 1px solid #e0e0e0;
  border-radius: 8px;
}

.nodes-container {
  position: fixed;
  left: 5px;
  top: 55px;
  height: calc(100vh - 100px);
  padding: 10px 20px;
}

.edit-node-container {
  position: fixed;
  right: 5px;
  top: 55px;
  height: calc(100vh - 100px);
  padding: 10px 20px;
  min-width: 350px;
  max-width: 400px;
}

.node-select-button {
  color: #373737;
}

.node-select-button:hover {
  font-weight: bold;
  cursor: pointer;
}

.selected-node {
  font-weight: bold;
  color: #960000;
  cursor: pointer;
}

.node-text-edit-field {
  padding: 7px;
  margin: 5px 0;
  width: 100%;
}

.node-edit-save-button {
  padding: 3px 7px;
  margin: 5px;
  background-color: #ffffff;
  border-radius: 7px;
  border: 1px solid #373737;
}

.node-edit-save-button:hover {
  background-color: #dddddd;
  cursor: pointer;
}

.hr {
  margin: 10px 0;
}



.checkbox-green {
	display: inline-block;
	height: 20px;
	line-height: 28px;
	margin-right: 10px;
	position: relative;
	vertical-align: middle;
	font-size: 14px;
	user-select: none;
}
.checkbox-green .checkbox-green-switch {
	display: inline-block;
	height: 20px;
	width: 90px;
	box-sizing: border-box;
	position: relative;
	border-radius: 2px;
	background: #848484;
	transition: background-color 0.3s cubic-bezier(0, 1, 0.5, 1);
}
.checkbox-green .checkbox-green-switch:before {
	content: attr(data-label-on);
	display: inline-block;
	box-sizing: border-box;
	width: 45px;
	padding: 0 8px;
	position: absolute;
	top: 0;
	left: 45px;
	text-transform: uppercase;
	text-align: center;
	color: rgba(255, 255, 255, 0.5);
	font-size: 10px;
	line-height: 20px;
}
.checkbox-green .checkbox-green-switch:after {
	content: attr(data-label-off);
	display: inline-block;
	box-sizing: border-box;
	width: 44px;
	border-radius: 1px;
	position: absolute;
	top: 1px;
	left: 1px;
	z-index: 5;
	text-transform: uppercase;
	text-align: center;
	background: white;
	line-height: 18px;
	font-size: 10px;
	color: #777;
	transition: transform 0.3s cubic-bezier(0, 1, 0.5, 1);
}
.checkbox-green input[type="checkbox"] {
	display: block;
	width: 0;
	height: 0;
	position: absolute;
	z-index: -1;
	opacity: 0;
}
.checkbox-green input[type="checkbox"]:checked + .checkbox-green-switch {
	background-color: #848484;
}
.checkbox-green input[type="checkbox"]:checked + .checkbox-green-switch:before {
	content: attr(data-label-off);
	left: 0;
}
.checkbox-green input[type="checkbox"]:checked + .checkbox-green-switch:after {
	content: attr(data-label-on);
	color: #848484;
	transform: translate3d(44px, 0, 0);
}

/* Hover */
.checkbox-green input[type="checkbox"]:not(:disabled) + .checkbox-green-switch:hover {
	cursor: pointer;
}

/* Disabled */
.checkbox-green input[type=checkbox]:disabled + .checkbox-green-switch {
	opacity: 0.6;
	filter: grayscale(50%);
}

/* Focus */
.checkbox-green.focused .checkbox-green-switch:after {
	box-shadow: inset 0px 0px 4px #ff5623;
}
</style>
