<template>
  <div class="annotation-box"
       :class="{draggable: type}"
       :style="style"
       @mousedown.stop.prevent="moveSelf" @touchstart.stop.prevent="moveSelf">
    <div class="nw" @mousedown.stop.prevent="resizeSelf('nw')" @touchstart.stop.prevent="resizeSelf('nw')"></div>
    <div class="nn" @mousedown.stop.prevent="resizeSelf('nn')" @touchstart.stop.prevent="resizeSelf('nn')"></div>
    <div class="ne" @mousedown.stop.prevent="resizeSelf('ne')" @touchstart.stop.prevent="resizeSelf('ne')"></div>
    <div class="ww" @mousedown.stop.prevent="resizeSelf('ww')" @touchstart.stop.prevent="resizeSelf('ww')"></div>

    <div class="buttons">
      <template v-if="!immutable">
        <div v-if="position.label" class="label-text">{{ currentLabel ? currentLabel.name : 'unknown label' }}</div>

        <img v-if="confirmationButton"
             alt="confirm" src="@/assets/icons/check.svg"
             @click.stop.prevent="confirmSelf"
             @touchstart.stop.prevent="confirmSelf"
             @mousedown.stop.prevent>
        <img v-if="labelButton"
             alt="label" src="@/assets/icons/tag.svg"
             @click.stop.prevent="showLabelSelection = true"
             @touchstart.stop.prevent="showLabelSelection = true"
             @mousedown.stop.prevent>
        <img alt="delete" src="@/assets/icons/trash.svg"
             @click.stop.prevent="deleteSelf"
             @touchstart.stop.prevent="deleteSelf"
             @mousedown.stop.prevent>
      </template>
    </div>

    <select v-if="!immutable && showLabelSelection"
            @touchstart.stop @mousedown.stop
            @change="labelSelf"
            @focusout="showLabelSelection = false">
      <option value="">None</option>

      <option v-for="label in labelList"
              :key="label.id"
              :value="label.id"
              :selected="label === currentLabel">
        {{ label.name }}
      </option>
    </select>

    <div class="ee" @mousedown.stop.prevent="resizeSelf('ee')" @touchstart.stop.prevent="resizeSelf('ee')"></div>
    <div class="sw" @mousedown.stop.prevent="resizeSelf('sw')" @touchstart.stop.prevent="resizeSelf('sw')"></div>
    <div class="ss" @mousedown.stop.prevent="resizeSelf('ss')" @touchstart.stop.prevent="resizeSelf('ss')"></div>
    <div class="se" @mousedown.stop.prevent="resizeSelf('se')" @touchstart.stop.prevent="resizeSelf('se')"></div>
  </div>
</template>

<script>
export default {
  name: "annotation-box",
  props: ['type', 'image', 'position', 'socket', 'boxUrl', 'labels', 'supports'],
  data: function () {
    return {
      showLabelSelection: false
    }
  },
  computed: {
    immutable: function () {
      return !this.type;
    },
    backgroundColor: function () {
      switch (this.type) {
        case 'user':
          return 'rgba(255, 0, 0, 0.3)';
        case 'pipeline':
          return 'rgba(0, 0, 255, 0.3)';
        default:
          return 'rgba(255, 255, 255, 0.3)';
      }
    },
    confirmationButton: function () {
      return this.type === 'pipeline';
    },
    labelButton: function () {
      return this.supports.includes('labeled-bounding-boxes') && this.type !== 'pipeline';
    },
    labelList: function () {
      return Object.keys(this.labels).map(key => this.labels[key]);
    },
    currentLabel: function () {
      if (this.position.label in this.labels)
        return this.labels[this.position.label];
      else
        return false;
    },
    style: function () {
      const left = this.image.left;
      const top = this.image.top;
      const width = this.image.width;
      const height = this.image.height;

      return {
        left: (left + this.position.x * width) + 'px',
        top: (top + this.position.y * height) + 'px',
        width: (this.position.w * width) + 'px',
        height: (this.position.h * height) + 'px',
        backgroundColor: this.backgroundColor
      }
    }
  },
  methods: {
    confirmSelf: function () {
      this.updateSelf(this.position);
    },
    labelSelf: function (event) {
      const options = event.target.options;
      const option = options[options.selectedIndex];
      const value = option.value;

      if (value)
        this.position.label = value;
      else
        delete this.position.label;

      this.updateSelf(this.position);
      this.showLabelSelection = false;
    },
    deleteSelf: function () {
      this.socket.post(this.boxUrl, {delete: true});
      this.$emit('update', true);
    },
    moveSelf: function (event) {
      this.$emit('move', event, this.position, this.updateSelf);
    },
    resizeSelf: function (mode) {
      this.$emit('resize', this.position, mode, this.updateSelf);
    },
    updateSelf: function (value) {
      if ('label' in this.position && !('label' in value))
        value.label = this.position.label;

      this.socket.post(this.boxUrl, value);
      this.$emit('update', true);
    }
  }
}
</script>

<style scoped>
.annotation-box {
  position: absolute;
}

.annotation-box.draggable {
  display: grid;
  grid-template-rows: 10px auto 10px;
  grid-template-columns: 10px auto 10px;
}

.buttons {
  display: flex;
  justify-content: center;
  align-items: center;
  position: relative;
}

img {
  width: 2rem;
  filter: invert(1);
  opacity: 0.9;
}

.nn, .ss {
  cursor: ns-resize;
}

.ww, .ee {
  cursor: ew-resize;
}

.ne, .sw {
  cursor: nesw-resize;
}

.nw, .se {
  cursor: nwse-resize;
}

select {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
}

.label-text {
  position: absolute;
  bottom: 0;
  color: whitesmoke;
  font-size: 80%;
}
</style>