<template>
  <g
    class="flow-node"
    :class="{'flow-node--dragging':dragging}"
    @mousedown="$emit('nodePointerDown',$event)"
  >
    <rect
      ref="body"
      class="flow-node__body"
      :class="{'flow-node__body--dragging':dragging}"
      v-bind="bodyProps"
    />
    <text
      ref="label"
      class="flow-node__label"
      v-bind="labelProps">
      {{ label }}
    </text>

    <!-- input -->
    <circle
      class="flow-node__socket flow-node__socket--inputs"
      v-for="(inp,i) in inputs"
      v-bind="inputProps(i)"
      :data-nodeid="id"
      :data-in="i"
      :class="{'flow-node__socket--match': inp == match.in}"
      :key="'in'+i"
      @mousedown.stop.prevent="socketPointerDown($event, {in:i})"
    />
    <!-- output -->
    <circle
      v-if="output"
      class="flow-node__socket flow-node__socket--outputs"
      :data-nodeid="id"
      :data-out="0"
      :key="'out'+0"
      :class="{ 'flow-node__socket--match': output == match.out}"
      v-bind="outputProps(0)"
      @mousedown.stop.prevent="socketPointerDown($event, {out:0})"
    />
  </g>
</template>

<script>

export default {
  name: 'FlowNode',
  props: {
    'id': {type: String, required: true},
    'label': {type: String, default: ''},
    'type': {type: String, default: ''},
    'inputs': {type: Array, default: () => []},
    'output': {type: String, default: ''},
    'match': {type: Object, default: () => {}},
    'dragging': {type: Boolean, default: false},

    'color': {type: String, default: '#777'},
    'textColor': {type: String, default: '#fff'}
    // 'value': {type: Object, default: () => {}}
  },
  data () {
    return {
      // maintain reference here?
      labelRect: {x: 0, y: 0, width: 0, height: 0},
      bodyRect: {x: 0, y: 0, width: 0, height: 0}
    }
  },
  computed: {
    labelProps () {
      return {
        x: -this.labelRect.width / 2,
        y: 5,
        fill: this.textColor
      }
    },
    bodyProps () {
      const width = this.labelRect.width + 32
      const rect = {
        x: -width / 2,
        y: -50,
        width: width,
        height: 100,
        fill: this.color
      }
      if (this.type === 'circle') {
        rect.rx = width
        rect.ry = width
      }
      return rect
    },
    inputProps () {
      return (i) => {
        const {x, y} = this.inputPos(i)
        return {
          transform: `translate(${x} ${y})`,
          r: 5
        }
      }
    },
    outputProps () {
      return (i) => {
        const {x, y} = this.outputPos(i)
        return {
          transform: `translate(${x} ${y})`,
          r: 5
        }
      }
    }
  },
  watch: {
    // the only thing now that affects geometry
    'label' () {
      this.$nextTick(() => {
        this.labelRect = this.$refs.label.getBBox()
      })
    }
  },
  mounted () {
    // After render
    this.$nextTick(() => { // after mount we reupdate with new values
      if (!this.$refs.label) return
      this.labelRect = this.$refs.label.getBBox()
      this.$forceUpdate()
    })
  },
  methods: {
    inputPos (i) {
      const ilen = this.inputs.length
      if (ilen === 0) return {}
      const d = this.bodyProps.height / (ilen * 2)
      return {
        x: this.bodyProps.x + 8,
        y: this.bodyProps.y + d + (i * 2 * d)
      }
    },
    outputPos (i) {
      const rect = this.bodyProps
      return {
        x: rect.x + rect.width - 8,
        y: 0
      }
    },
    socketPointerDown (ev, socket) {
      this.$emit('socketPointerDown', ev, socket)
    }

  }
}
</script>
<style lang="scss">
.flow-node {
  filter: url(#highlight-border);
}
svg:not(.activity) .flow-node:hover .flow-node__body{
  stroke-width:1;
  stroke:black;
  cursor:move;

}
.flow-node__socket {
  stroke-width:1;
  cursor:pointer;
  fill: #AFAFAF;
  stroke: #AFAFAF;
}

.flow-node__socket:not(.flow-node__socket--match):hover {
  stroke-width:10;
}
.flow-node__socket--match {
  stroke-width:10;
  stroke:#2a2;
  fill:#2a2;
  filter: url(#highlight-border);
}

.flow-node__label {
  stroke:none;
  pointer-events:none;
  user-select:none;
  fill:white;
}
</style>
