<template>
  <div class="flow-main" :class="{dark:dark}">
    <div class="app-header">
      Flow
      <button @click="dark=!dark">{{ dark?'light':'dark' }}</button>
    </div>
    <div class="app-horizontal">
      <div class="app-flow-container">
        <div class="app-watermark">PROTOTYPE</div>
        <div class="app-info">
          <h4>HELP</h4>
          <ul>
            <li><b>Pan</b>: Drag with Middle Mouse or Ctrl+left mouse button</li>
            <li><b>Zoom</b>: Mouse wheel up and down to zoom in and out</li>
            <li><b>New Node</b>: Create a node by dragging a fn from left panel into area</li>
            <li><b>Remove Node</b>: Middle click in a node to remove a node</li>
            <li><b>Inspect node</b>: Double click on a node to get detailed information</li>
            <li><b>Move Node</b>: Mouse click and drag</li>
            <li><b>Links</b>: Press [shift] and Drag from a node/socket to a socket highlighted in green</li>
            <li><b>Links(alternative)</b>: Toggle socket visualisation in the panel and Drag from a socket to a socket highlighted in green</li>
            <li><b>Remove Link</b>: Simple click on the link when it turns red</li>
          </ul>

          <h4>TODO:</h4>
          <ul>
            <li>UX/UI: Undo changes</li>
            <li>UX/UI: Special nodes with display capabilities (images,datatables,...)</li>
            <li>UX/UI: Group nodes into a single box, exposing inputs and outputs</li>
            <li>UX/UI: Implement touch</li>
            <li>UX/UI: drop link in node to link to next compatible available input</li>
            <li>Registry: Synchronize registry with server(GET)</li>
            <li>Collaboration: Better concurrent editing/message passing (testing)</li>
            <li>Collaboration: Improve document synchronization</li>
            <li>FlowServer: Build the graph on the server and run</li>
            <li>FlowPkg: Create training mechanism</li>
            <li>FlowPkg: matrix pooling function example</li>
          </ul>
          <br>
          <small>&copy; Luis Figueiredo (luisf@hexasoftware.com)</small>
        </div>

        <!--:value="nodeData"
        @input="documentUpdate"-->
        <hx-split
          dir="horizontal"
          :resizeable="funcsActive"
          :split="funcsActive?funcsSize:'0px'"
          @onSplitResize="funcsSizeUpdate"

        >
          <div class="flow-panel__container">
            <div class="flow-panel__selector">
              <button :class="{active:panel=='palette'}" @click="panel='palette'">Funcs</button>
              <button :class="{active:panel=='inspector'}" @click="panel='inspector';nodeInspect = nodeActive">Inspector</button>
            </div>
            <transition name="fade">
              <flow-funcs
                v-show="panel=='palette'"
                :registry="registry"
                @toggleResizeable="funcsResizeable=!funcsResizeable"
                @toggleStickySockets="managerStickySockets=!managerStickySockets"
              />
            </transition>
            <transition name="fade">
              <flow-inspector
                ref="inspector"
                v-show="panel=='inspector'"
                :registry="registry"
                :activity="activity"
                :node-inspect="nodeInspect"
                @nodeProcess="nodeProcess($event)"
              />
            </transition>
          </div>
          <flow-manager
            ref="flowManager"
            :activity="activity"
            :registry="registry"
            @funcsPanelToggle="funcsActive=!funcsActive"
            @nodeInspect="nodeInspectStart(...arguments)"
            @nodeDblClick="nodeInspectStart(...arguments,true)"
            @documentSave="documentSave"

            width="100%"
            height="100%"/>
        </hx-split>
      </div>
      <div class="app-chat">
        <app-chat/>
      </div>
      <!-- Node inspector -->
      <!-- Move this to a different place -->
      <!-- And rename it to inspector -->
      <!--<hx-modal
        class="flow-modal"
        v-if="nodeInspect"
        @close="nodeInspect=null"
        @keydown.esc="nodeInspect=null"
      >
        <div slot="header">Node inspector:</div>
        <div slot="body" class="flow-modal__body">
          <div class="flow-modal__info">
            <svg class="flow-view preview activity flow-node--detail flow-node--activity flow-linking" width="100%" height="100%" viewBox="0 0 300 200">
              <flow-panzoom>
                <flow-node
                  style="pointer-events:none"
                  ref="modalPreviewNode"
                  :id="nodeInspect.id"
                  transform="translate(150,100)"
                  :match="{}"
                  :label="nodeInspect.label"
                  :inputs= "registry[nodeInspect.src].inputs"
                  :output= "registry[nodeInspect.src].output"
                  :activity= "activity[nodeInspect.id]"
                  :nodeStyle= "registry[nodeInspect.src].style"
                />
              </flow-panzoom>
            </svg>
            <div class="flow-modal__params" v-if="nodeInspect.prop" >
              <h3>Node Parameters</h3>
              <div class="flow-modal__param" v-for="(v,k) in nodeInspect.prop">
                <label>{{ k }}</label>
                <input
                  ref="nodeInspectProp"
                  type="text"
                  @keydown.prevent.stop.enter="nodeInspect=null;"
                  @keydown.esc="nodeInspect=null"
                  v-model="nodeInspect.prop[k]">
              </div>
            </div>
            <div class="flow-modal__properties">

              <h3>Node Properties</h3>
              <label>Description</label>
              <div class="property">Bogus description</div>
              <label>Help</label>
              <div class="property">Connect to input a thing and goes to output another thing</div>
              <div v-if="activity && activity[nodeInspect.id] && activity[nodeInspect.id].data" class="flow-modal__properties-result">
                <label>Result</label>
                <div class="property">{{ activity && activity[nodeInspect.id] && activity[nodeInspect.id].data }}</div>
              </div>
              <div v-if="activity && activity[nodeInspect.id] && activity[nodeInspect.id].error" class="flow-modal__properties-error">
                <label>Error</label>
                <div class="property">{{ activity && activity[nodeInspect.id] && activity[nodeInspect.id].error }}</div>
              </div>
              <div style="flex: 1 0 100%;">&nbsp;</div>
              <button class="flow-modal__button-run primary-inverse" @click="nodeProcess(nodeInspect)">Run</button>
            </div>
          </div>
          <label>label</label>
          <input
            ref="modalInput"
            type="text"
            @keydown.enter="nodeInspect=null;"
            @keydown.esc="nodeInspect=null"
            v-model="nodeInspect.label" >
        </div>
        <div class="flow-modal__footer" slot="footer">
          <button class="primary" @click="nodeInspect=false">OK</button>
        </div>
      </hx-modal>-->

    </div>
  </div>
</template>
<script>
import AppChat from '@/components/chat'
import FlowManager from '@/components/flow/manager'
import FlowNode from '@/components/flow/node'
import FlowPanzoom from '@/components/flow/panzoom'
import FlowFuncs from './panel-funcs'
import FlowInspector from './panel-inspector'
import HxSplit from '@/components/shared/hx-split'
import HxModal from '@/components/shared/hx-modal'
import defRegistry from './defregistry'
import 'reset-css/reset.css'

import '@/assets/dark-theme.css'
import '@/assets/style.css'
// import nodeData from './nodedata'

export default {
  components: {FlowManager, FlowNode, FlowPanzoom, FlowInspector, FlowFuncs, HxSplit, HxModal, AppChat},
  data () {
    return {
      registry: JSON.parse(JSON.stringify(defRegistry)),
      activity: {},

      panel: 'palette',

      nodeActive: null,
      nodeInspect: null,

      funcsSize: '250px',
      funcsActive: true,
      funcsResizeable: false,

      dark: false
    }
  },
  watch: {
    nodeInspect: {
      handler (val, oldVal) {
        if (!val === null && !oldVal) { return }
        if (!val) {
          this.$refs.flowManager.sendDocumentUpdate()
          return
        }
        this.$refs.flowManager.sendFlowEvent('nodeUpdate', [this.nodeInspect])
      },
      deep: true
    }
  },

  mounted () {
    // Handle incoming things
    this.$flowService.on('sessionJoin', (v) => {
      if (v.id !== this.$route.params.sessId) {
        this.$router.push('/' + v.id) // Swap to ID
      }
    })
    this.$flowService.on('registry', (v) => {
      let res = {}
      for (let k of Object.keys(v.data)) {
        const e = v.data[k]
        res[k] = {
          categories: e.categories,
          inputs: e.inputs,
          inputDesc: e.inputDesc,

          output: e.output,
          outputDesC: e.outputDesc,
          style: e.extra && e.extra.style
        }
      }
      this.registry = Object.assign({}, defRegistry, res)
    })
    this.$flowService.on('nodeActivity', (v) => {
      this.activity = v.data || {}
    })
    this.$flowService.on('sessionLog', (v) => {
      // Make this elsewhere
      console.log(v.data)
    })

    // Connected
    this.$flowService.connected(() => {
      // Make this in a service
      if (this.$route.params.sessId === undefined) {
        this.$flowService.sessionNew()
        return
      }
      this.$flowService.sessionLoad(undefined, this.$route.params.sessId)
    })
  },
  methods: {
    nodeInspectStart (node, changePane) { // node
      this.nodeActive = node
      if (changePane) this.panel = 'inspector'
      if (this.panel !== 'inspector') {
        return
      }
      this.nodeInspect = node

      // if (!changePane) { return }
      this.$nextTick(() => {
        // panel input
        if (!this.$refs.inspector) { return }
        const insp = this.$refs.inspector
        let targetInput = this.$refs.inspector.$refs.labelInput
        if (insp.$refs.props && insp.$refs.props.length > 0) {
          targetInput = insp.$refs.props[0]
        }

        targetInput.setSelectionRange(0, targetInput.value.length)
        targetInput.focus()
      })
    },
    nodeProcess (node) {
      this.$flowService.nodeProcess(node.id)
    },
    funcsSizeUpdate (ev, size) {
      this.funcsSize = size
    },
    documentSave () {
      this.$flowService.documentSave()
    }
    // Update individual nodes/links
  }
}

</script>
<style>
.flow-main {
  height:100%;
  display:flex;
  flex-direction: column;
}

.flow-main .app-flow-container {
  position:relative;
  flex:1;
}

.flow-main .flow-container {
  position:absolute;
  top:0;
  right:0;
  bottom:0;
  left:0;
}

.flow-main .app-header {
  padding:0 14px;
  height: 50px;
  display:flex;
  justify-content: space-between;
  align-items: center;
}

.flow-main  .app-info {
  opacity:0.5;
  color: #aaa;
  font-size:10px;
  margin:20px;
  padding:20px;
  position:absolute;
  right:0;
  bottom:3%;
}

.flow-main .app-watermark {
  position:absolute;
  top:40%;
  text-align:center;
  width:100%;
  font-size:100px;
  text-shadow: 1px 1px 1px rgba(255,255,255,0.5), -1px -1px 1px rgba(0,0,0,0.05);
}

.split .splitter{
  flex-basis:0;
  position:relative;
  background: rgba(208,208,208,0.9);
}

.split:not(.resizeable) .content:first-child {
  transition: all var(--transition-speed);
}

.split.resizeable.horizontal .splitter::after {
  opacity:0.4;
  display:flex;
  justify-content: center;
  align-items: center;
  z-index:100;
  content:" ";
  position:absolute;
  top:0%;
  bottom:0%;
  left:0;
  width:10px;
  background: rgba(0,0,0,0.5);
  transition: var(--transition-speed);
}

.app-horizontal {
  height:100%;
  max-height:100%;
  display:flex;
  position:relative;
  flex-flow:row;
  overflow:hidden;
}

.app-chat {
  position:absolute;
  top:0;
  right:0;
  height:100%;
}

.flow-panel__container {
  display:flex;
  flex-flow:column;
  flex:1;
  overflow:hidden;
}

.flow-panel__selector {
  color: var(--normal);
  display:flex;
  align-content: stretch;
  flex-shrink: 0;
  height:50px;
  border-bottom:solid 1px var(--primary);
}

.flow-panel__selector button{
  flex:1;
}

/*
.flow-modal__info {
  padding-bottom:20px;
  display:flex;
  flex-flow:row;
}

.flow-modal__info > * {
  margin-right:10px;
  flex:1;
}

.flow-modal__body label {
  font-size:14px;
  display:flex;
  flex-flow:row;
  font-weight:bold;
  padding-bottom:10px;
}

.flow-modal__info .property {
  padding-left:20px;
  font-size:12px;
}

.flow-modal__properties-error .property{
  color: red;
}

.flow-modal__button-run {
  align-self: flex-end;
  width:100%;
}

.flow-modal__footer {
}*/

</style>
