<template>
  <div>
    <input type="hidden" :name="name" :value="JSON.stringify(columns)">
    <table class="editor-table">
      <thead>
        <tr>
          <th></th>
          <th>Name</th>
          <th>Type</th>
          <th>Title</th>
          <th></th>
        </tr>
      </thead>
      <transition-group name="col-list" tag="tbody" ref="col-list">
        <tr v-for="(col, i) in columns" :key="col.id" :ref="'col' + i" :class="{dragging: col._dragging}">
          <td class="btn-group">
            <button class="btn btn-outline-secondary drag-btn" @mousedown="beginDrag(i, $event)">
              <v-icon class="fa-bars" alt="Drag" />
            </button>
            <a href="" :class="['btn', 'btn-outline-secondary', {disabled: i==0}]" @click.prevent="move(i, -1)">
              <v-icon class="fa-chevron-up" alt="Move Up" />
            </a><a href="" :class="['btn', 'btn-outline-secondary', {disabled: i == (columns.length-1)}]" @click.prevent="move(i, 1)">
              <v-icon class="fa-chevron-down" alt="Move Down" />
            </a>
          </td>

          <td>
            <input v-model="col.name" class="form-control" type="text" style="width: 140px">
          </td>

          <td>
            <select v-model="col.type" class="form-control custom-select" style="width: 110px">
              <option v-for="t in colTypes" :value="t">{{t}}</option>
            </select>
          </td>

          <td>
            <input v-model="col.title" class="form-control" type="text" style="width: 170px">
          </td>

          <td class="text-nowrap">
            <a href="" :class="['mr-1', 'btn', 'btn-outline-secondary', 'delete-btn', {disabled: i==0}]" @click.prevent="delCol(i)">
              <v-icon class="fa-trash-o" alt="Delete column" />
            </a><!--
            --><a href="" class="btn btn-outline-secondary" v-if="i === columns.length - 1"
                  @click.prevent="addCol()">
              <v-icon class="fa-plus" alt="Add Column" />
            </a>
          </td>
        </tr>
      </transition-group>
    </table>
  </div>
</template>

<style lang="scss" scoped>
  @import "base";

  table {
    border-collapse: collapse;
  }

  td, th {
    @include pr(1);
    @include py(1);
  }

  tr.dragging {
    position: relative;
    z-index: 1;
    background-color: $body-bg;
  }
  tr.dragging .drag-btn {
    // fake hover
    background-color: $secondary;
    color: color-yiq($secondary);
  }

  .col-list-enter-active {
    transition: all .3s cubic-bezier(.2, .3, 0, 1);
  }

  .col-list-enter {
    opacity: 0;
    transform: translateY(100%);
  }
  .col-list-leave {
    // approximate position of delete button
    clip-path: circle(calc(100% + 5em) at calc(100% - 4em) 50%);
  }
  .col-list-leave-active .delete-btn {
    animation: col-list-leave-delete-btn .3s forwards;
  }
  .col-list-leave-active {
    transition: all .3s cubic-bezier(.4, .1, .6, .9);
  }
  .col-list-leave-to {
    clip-path: circle(0 at calc(100% - 4em) 50%);
  }

  @keyframes col-list-leave-delete-btn {
    0% {
      transition-timing-function: cubic-bezier(.2, .4, .6, .9);
    }
    50% {
      transition-timing-function: cubic-bezier(.5, 0, .8, .5);
      transform: scale(1.1);
      opacity: 1;
    }
    100% {
      transform: scale(0);
      opacity: 0;
    }
  }

  .col-list-move {
    transition: transform .3s cubic-bezier(.2, .3, 0, 1);
  }
</style>

<script>
export default {
  props: {
    name: String,
    initialColumns: Array,
  },
  data: function() {
    return {
      columns: this.initialColumns,
      colTypes: ['string', 'int', 'float', 'bool'],
    }
  },
  methods: {
    delCol(n) {
      if (n == 0) return

      this.columns.splice(n, 1)
    },
    addCol() {
      this.columns.push({
        id: Math.random().toString(),
        name: '',
        type: 'string',
        title: '',
      })
    },
    move(i, dir) {
      let cur = this.columns[i];
      let next = this.columns[i+dir];
      this.$set(this.columns, i, next);
      this.$set(this.columns, i+dir, cur);
    },
    beginDrag(i, evt) {
      const column = this.columns[i];
      column._dragging = true;
      this.$set(this.columns, i, column); // notify vue

      let currentIndex = i;

      const dragMoveListener = e => {
        let cursorIndex = 0;

        // find cursor index by going through the list and adding the li
        // heights (can’t use their positions because they may be animating at
        // that moment)
        let accumY = this.$refs['col-list'].$el.getBoundingClientRect().top;
        for (let i = 0; i < this.columns.length; i++) {
          if (e.clientY > accumY) {
            cursorIndex = i;
          }
          accumY += $(this.$refs['col' + i]).outerHeight(true);
        }

        if (cursorIndex !== currentIndex) {
          this.move(currentIndex, cursorIndex - currentIndex);
          currentIndex = cursorIndex;
        }
      }

      const dragEndListener = e => {
        column._dragging = false;
        this.$set(this.columns, currentIndex, column); // notify vue

        $(window).off('mousemove', dragMoveListener);
        $(window).off('mouseup', dragEndListener);
      };

      $(window).on('mousemove', dragMoveListener);
      $(window).on('mouseup', dragEndListener);
    }
  }
}
</script>
