<template>
  <div>
    <div class="itf-segmeneted-control d-none d-lg-grid" :class="{'small': small}">
      <span v-if="!isUndefined" ref="slider" class="selection" :class="{'elevation-1': !disabled}"></span>

      <div class="option" v-for="(item, n) in itemsWithNames" :key="n">
        <label v-tooltip="tooltipCallback(item)" :key="n" :class="{'disabled': disabled || item[itemDisabled]}">
          <slot name="itemMarkup" :item="item" />
          <input
            ref="input"
            type="radio"
            :name="name"
            :value="n"
            :disabled="disabled || item[itemDisabled]"
            :checked="isChecked(item)"
            @change="onItemChanged(item)" />
          <span>
          <slot name="item" :item="item" :itemKey="n">{{item[itemText]}}</slot>
        </span>
        </label>
      </div>
    </div>
    <div class="d-lg-none">
      <itf-select
        :value="value"
        @input="$emit('input', $event)"
        :disabled="disabled"
        :options="itemsWithNames"
        :reduce="(item) => item[itemKey]"
        :get-option-label="(item) => item[itemText]"
      />
    </div>
  </div>
</template>
<script>
import { Vue, Component, Model, Prop, Watch } from 'vue-property-decorator';
import itfSelect from '../select/Select';
import tooltip from '../../directives/tooltip';

export default @Component({
  name: 'itfSegmentedControl',
  directives: {
    tooltip
  },
  components: {
    itfSelect
  }
})
class itfSegmentedControl extends Vue {
  @Model('input') value;
  @Prop({ type: Array, required: true }) items;
  @Prop({ type: String, default: 'Id' }) itemKey;
  @Prop({ type: String, default: 'Name' }) itemText;
  @Prop({ type: String, default: 'Disabled' }) itemDisabled;
  @Prop({ type: Boolean, default: false }) returnObject;
  @Prop({ type: Boolean, default: false }) disabled;
  @Prop({ type: Boolean, default: false }) small;
  @Prop({ type: Function, default: () => null }) tooltipCallback;

  timers = [];

  get name () {
    return `sc${this._uid}`;
  }

  get itemsWithNames() {
    return this.items.map((item, n) => {
      return {
        ...item,
        $itemName: this.disabled ? null : `item${this.name}${n}`
      };
    });
  }

  mounted () {
    this.$nextTick(() => this.init());
  }

  get itemValue () {
    if (typeof this.value === 'undefined' || this.value === null) {
      return this.value;
    }
    return typeof this.value === 'object' ? this.value[this.itemKey] : this.value;
  }

  isChecked (item) {
    return this.itemValue === item[this.itemKey];
  }

  @Watch('value')
  @Watch('items')
  onItemsChanged() {
    this.$nextTick(() => this.init());
  }

  get isUndefined () {
    return typeof this.value === 'undefined';
  }

  init() {
    this.$el.addEventListener('change', () => updatePillPosition(this));
    //window.addEventListener('resize', () => updatePillPosition(this.$el)); // Prevent pill from detaching from element when window resized. Becuase this is rare I haven't bothered with throttling the event

    updatePillPosition(this);

    function updatePillPosition (component) {
      component.timers.forEach((timer) => {
        clearTimeout(timer);
      });
      component.timers = [];
      component.$refs.input.forEach((elem, index) => {
        if (elem.checked) {
          component.$nextTick(() => moveBackgroundPillToElement(component, elem, index));
          component.timers = [
            setTimeout(() => moveBackgroundPillToElement(component, elem, index), 500),
            setTimeout(() => moveBackgroundPillToElement(component, elem, index), 750),
            setTimeout(() => moveBackgroundPillToElement(component, elem, index), 1500),
            setTimeout(() => moveBackgroundPillToElement(component, elem, index), 3000)
          ];
        }
      })
    }

    function moveBackgroundPillToElement (component, elem, index) {
      const slider = component.$refs.slider;
      if (slider) {
        slider.style.transform = 'translateX(' + (elem.offsetWidth * index) + 'px)';
      }
    }
  }

  onItemChanged (item) {
    if (this.disabled) {
      return;
    }
    this.$emit('input', this.returnObject ? item : item[this.itemKey]);
  }
}
</script>
