<template>
  <draggable
          :list="items"
          @start="drag=true"
          @end="drag=false"
          @change="change"
          group="items"
          class="episodeList"
          :disabled="$store.state.editingItem"
  >
    <CustomiseItem v-for="i in items.length"
                   :key="items[i - 1].url"
                   :item="items[i - 1]"
                   :start="times? times[i - 1].start : null"
                   :end="times? times[i - 1].end : null"
                   @remove="remove"
    />
  </draggable>
</template>

<script>
import draggable from "vuedraggable"
import CustomiseItem from "./CustomiseItem";


/**
 * @description The ArrangeItems component uses vue-draggable to enable CustomiseItem components to be rearranged.
 * @vue-prop {Array} items List of episodes in the draggable box.
 * @vue-prop {Number} [dayId=null] The id of the day that this component represents.
 *
 * @vue-computed times {Array<{start: Number, end: Number}>} The start and end times for each item.
 *
 * @vue-event assignItem {{item: HTMLElement, dayId: Number, prevOrder: Number, nextOrder: Number}} Emit a command to move an HTMLElement to a particular slot on a particular day.
 * @vue-event removeItem {{item: CustomiseItem, dayId: string}} Emit a command to remove an item from this component.
 */
export default {
  name: 'ArrangeItems',
  components: {
    CustomiseItem,
    draggable},
  props: {
    items: {type: Array, required: true}, // list of episodes selected
    dayId: {type: Number, required: false, default: null}
  },
  data: function() {
    return {}
  },
  computed: {
    times() {
      if(!this.dayId)
        return null;
      const config = this.$store.getters['workshop/Repository']().config;
      let times;
      if(config.yaml.start_times.length > this.dayId - 1) {
        times = config.yaml.start_times[this.dayId - 1].split('|');
      } else
        times = config.yaml.start_times[0].split('|');
      const start = parseInt(times[0]) * 60;
      let elapsed = parseInt(times[1]);

      return this.items.map(i => {
        const out = {
          start: [Math.floor((start + elapsed) / 60), (start + elapsed) % 60]
        };
        elapsed += parseInt(i.yaml.duration || "0") +
                parseInt(i.yaml.teaching || "0") +
                parseInt(i.yaml.exercises || "0");
        out.end = [Math.floor((start + elapsed) / 60), (start + elapsed) % 60];
        return out;
      });
    }
  },
  methods: {
    /**
     * Check a draggable event and process any updates needed.
     * @param evt {{added: Array<Object>, moved: Array<Object>}} Draggable drop event.
     */
    change(evt) {
      // Only monitor add events because the store will handle removals
      if(!evt.added && !evt.moved)
        return;
      const E = evt.added || evt.moved;
      const prevOrder = E.newIndex !== 0?
              this.items[E.newIndex - 1].yaml.order : null;
      const nextOrder = E.newIndex !== this.items.length - 1?
              this.items[E.newIndex + 1].yaml.order : null;
      const safeOrder = o => typeof o !== 'number' || isNaN(o)? null : o;
      this.$emit('assignItem', {
        item: E.element,
        dayId: this.dayId,
        prevOrder: safeOrder(prevOrder),
        nextOrder: safeOrder(nextOrder)
      });
    },
    /**
     * Remove an child item from the component.
     * @param item {Object} Item to remove.
     */
    remove(item) {this.$emit('assignItem', {item: item, dayId: ''})}
  }
}
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style lang="scss" scoped>
  .episodeList {user-select: none;}
</style>