<template>
  <div
    :class="b({ disabled })"
    @click.stop="onClick"
  >
    <div
      :class="b('bar')"
      :style="barStyle"
    >
      <span
        :class="b('button')"
        @touchstart="onTouchStart"
        @touchmove.prevent.stop="onTouchMove"
        @touchend="onTouchEnd"
        @touchcancel="onTouchEnd"
      />
    </div>
  </div>
</template>

<script>
import create from '../utils/create';
import Touch from '../mixins/touch';

export default create({
  name: 'slider',

  mixins: [Touch],

  props: {
    min: Number,
    value: Number,
    disabled: Boolean,
    max: {
      type: Number,
      default: 100
    },
    step: {
      type: Number,
      default: 1
    },
    barHeight: {
      type: String,
      default: '2px'
    }
  },

  computed: {
    barStyle() {
      return {
        width: this.format(this.value) + '%',
        height: this.barHeight
      };
    }
  },

  methods: {
    onTouchStart(event) {
      if (this.disabled) return;

      this.touchStart(event);
      this.startValue = this.format(this.value);
    },

    onTouchMove(event) {
      if (this.disabled) return;

      this.touchMove(event);
      const rect = this.$el.getBoundingClientRect();
      const diff = this.deltaX / rect.width * 100;
      this.updateValue(this.startValue + diff);
    },

    onTouchEnd() {
      if (this.disabled) return;
      this.updateValue(this.value, true);
    },

    onClick(event) {
      if (this.disabled) return;

      const rect = this.$el.getBoundingClientRect();
      const value = (event.clientX - rect.left) / rect.width * 100;
      this.updateValue(value, true);
    },

    updateValue(value, end) {
      value = this.format(value);
      this.$emit('input', value);

      if (end) {
        this.$emit('change', value);
      }
    },

    format(value) {
      return (Math.round(Math.max(this.min, Math.min(value, this.max)) / this.step) * this.step);
    }
  }
});
</script>
