<template>
  <div class="page-container md-layout-column" id="dashboard-container">

    <!-- toolbar -->
    <toolbar @showDrawerClicked="showDrawer = true"
             @applyClicked="performApply"
             :processing="anyPendingNodeMoves"
             :model-changed="modelChanged"
    />

    <!-- drawer -->
    <md-drawer :md-active.sync="showDrawer" md-swipeable>
      <workspace-drawer-content :pending-changes="pendingChanges"/>
    </md-drawer>

    <!-- workspace -->
    <md-content id="diagram-container">
      <simple-flowchart
          :scene.sync="model"
          @nodeDelete="enqueuePendingNodeDeletion"
          @nodeDataEdited="enqueuePendingNodeUpdate"
          @linkBreak="handleLinkBreak"
          @linkAdded="handleLinkAdd"
          @nodeMoved="handleNodeMove"
      />
      <element-adder @addElement="newElement"/>
    </md-content>

  </div>
</template>

<script>

import SimpleFlowchart from '@/simple-flowchart';
import ElementAdder from "@/components/ElementAdder";
import WorkspaceDrawerContent from "@/components/WorkspaceDrawerContent";
import Toolbar from "@/components/Toolbar";

import {some} from 'lodash';

export default {
  name: 'Dashboard',
  components: {
    SimpleFlowchart,
    ElementAdder,
    WorkspaceDrawerContent,
    Toolbar
  },
  data: () => ({
    showDrawer: false,
    idGenerator: 1,
    pendingChanges: {
      created: [],
      updated: [],
      deleted: [] // Stores apiId instead of localId
    },
    pendingNodeMoves: 0, // count of inflight coord modifications
    model: {
      centerX: 0,
      centerY: 0,
      scale: 1,
      nodes: [],
      links: []
    }
  }),
  methods: {
    newElement(type) {
      this.showNewElementChooser = false;

      let newNode = {
        x: 10,
        y: 10,
        type,
        apiId: null
      }

      switch (type) {
        case "ingest":
          newNode.data = {
            url: "",
            streamkey: "demokey"
          }
          break;
        case "encoder":
          newNode.data = {
            bitrate: 0,
            width: 0,
            height: 0
          }
          break;
        case "restreamer":
          newNode.data = {
            url: "",
            streamkey: ""
          }
          break;
      }

      newNode.id = this.idGenerator;
      this.idGenerator++;

      this.model.nodes.push(newNode);
      //this.pendingChanges.created.add(newNode.id);
      this.enqueuePendingNodeCreation(newNode.id);

    },
    // Vuejs can not track changes of a set, so we do this magic hack to fix it
    enqueuePendingNodeDeletion({id, apiId}) {
      let pending_deletes = new Set(this.pendingChanges.deleted);
      let pending_updates = new Set(this.pendingChanges.updated);
      let pending_creations = new Set(this.pendingChanges.created);

      // This stuff is here to prevent the creation and deletion of an object in the same transaction
      if (pending_creations.has(id)) {
        pending_creations.delete(id);
      } else {
        if (apiId) {
          pending_deletes.add(apiId);
        }
      }

      pending_updates.delete(id);

      this.pendingChanges.deleted = Array.from(pending_deletes);
      this.pendingChanges.updated = Array.from(pending_updates);
      this.pendingChanges.created = Array.from(pending_creations);
    },
    enqueuePendingNodeUpdate(id) {
      let pending_updates = new Set(this.pendingChanges.updated);
      pending_updates.add(id);
      this.pendingChanges.updated = Array.from(pending_updates);
    },
    enqueuePendingNodeCreation(id) {
      let pending_creations = new Set(this.pendingChanges.created);
      pending_creations.add(id);
      this.pendingChanges.created = Array.from(pending_creations);
    },
    // --- end of magic hack
    handleNodeMove(id) {
      console.log(id);
      const moved_node = this.model.nodes.find((node) => node.id === id);
      console.log(moved_node);
      if ((!moved_node) || (!moved_node.apiId)) {
        return;
      }
      console.log("Anyád")
      this.pendingNodeMoves++;
      this.$api.put(`objects/streamerobjects/coordmodify/${moved_node.apiId}`, {
        x: moved_node.x,
        y: moved_node.y
      }).then(() => {
        this.pendingNodeMoves--;
      }).catch(() => {
        this.pendingNodeMoves--;
      });

    },
    handleLinkBreak({from, to}) {
      this.enqueuePendingNodeUpdate(from);
      this.enqueuePendingNodeUpdate(to);
    },
    handleLinkAdd({from, to}) {
      this.enqueuePendingNodeUpdate(from);
      this.enqueuePendingNodeUpdate(to);
    },
    performApply() {
      this.pendingChanges.created.forEach((id) => {
        this.model.nodes.find((n) => n.id === id).apiId = 'a';
      });
      this.pendingChanges = {
        deleted: [],
        created: [],
        updated: []
      }
    }
  },
  computed: {
    modelChanged() {
      return some(this.pendingChanges, (o) => o.length > 0);
    },
    anyPendingNodeMoves() {
      return this.pendingNodeMoves > 0;
    }
  }

}
</script>

<style scoped>
#dashboard-container {
  height: 100%;
}

#diagram-container {
  height: calc(100% - 64px);
}
</style>