<template>
  <div class="dof-gear" ref="root" @touchmove="onTouchMove">
    <template v-for="(v, i) in ranges">
      <div ref="bar" :key="i" class="dof-gear-item" @click="() => onClick(v)">
        <div v-if="!readonly" class="dof-gear-item-anchor">
          <div class="dof-gear-item-anchor-angle" :style="getAngleStyle(v)"></div>
        </div>
        <div class="dof-gear-item-track" :style="trackStyle">
          <div class="dof-gear-item-bar" :style="getBarStyle(v)"></div>
        </div>
        <text v-if="v.gear" class="dof-gear-item-gear" :style="gearStyle">{{ v.gear }}</text>
      </div>
      <div v-if="!isLast(i)" class="dof-gear-gap" :key="`gap-${i}`"></div>
    </template>
  </div>
</template>

<script>
import { Range } from './range.js'
import { getBoundingClientRectBase } from '../utils/dom.js'
export default {
  props: {
    barWidth: {
      type: Number,
      default: 16
    },
    height: {
      type: Number,
      default: 96
    },
    color: {
      type: String,
      default: '#F2F2F2'
    },
    fullColor: {
      type: String,
      default: '#1A4FB6'
    },
    setColor: {
      type: String,
      default: '#F56428'
    },
    ranges: {
      type: Array,
      default: () => Range.Default
    },
    value: {
      type: Number,
      default: 5
    },
    gear: {
      type: Number,
      default: 1
    },
    readonly: {
      type: Boolean,
      default: true
    },
    grow: {
      type: Number,
      default: 42
    },
    swipable: {
      type: Boolean,
      default: false
    },
    offset: {
      type: Number,
      default: 5
    },
    delay: {
      type: Number,
      default: 100
    }
  },
  model: {
    prop: 'gear',
    event: 'change'
  },
  data() {
    return {
      rects: []
    }
  },
  computed: {
    gearRanges() {
      return this.ranges.filter(x => x.gear)
    },
    minGearRange() {
      return this.gearRanges[0]
    },
    maxGearRange() {
      return this.gearRanges[this.gearRanges.length - 1]
    },
    gearRange() {
      return this.gearRanges.find(x => x.gear === this.gear)
    },
    trackStyle() {
      const style = {
        width: `${this.barWidth}px`,
        height: `${this.height}px`,
        borderRadius: `${this.barWidth / 2}px`
      }
      if (!this.readonly) {
        style.height = `${this.height + this.grow}px`
      }
      return style
    },
    gearStyle() {
      const style = {
        color: this.fullColor
      }
      return style
    }
  },
  mounted() {
    if (this.swipable && !this.readonly) {
      setTimeout(() => this.initRect(), this.delay)
    }
  },
  methods: {
    initRect() {
      const dom = weex.requireModule('dom')
      this.ranges.forEach((range, i) => {
        if (range.gear) {
          getBoundingClientRectBase(dom, this.$refs['bar'][i], res => {
            this.rects.push({
              ...range,
              left: res.size.left,
              dis: res.size.left + res.size.width
            })
          })
        }
      })
    },
    isLast(index) {
      return index >= this.ranges.length - 1
    },
    isSet(range) {
      return range.gear == this.gearRange.gear
    },
    isPreserve(range) {
      return range.min >= this.gearRange.max
    },
    isWaiting(range) {
      return range.min > this.value && range.max <= this.gearRange.min
    },
    isFull(range) {
      return range.min <= this.value
    },
    getBarStyle(range) {
      const style = {
        width: `${this.barWidth}px`,
        height: `${this.height}px`,
        borderRadius: `${this.barWidth / 2}px`,
        opacity: 1
      }
      if (!this.readonly && this.isSet(range)) {
        style.height = `${this.height + this.grow}px`
      }
      if (this.isFull(range)) {
        style.backgroundColor = this.fullColor
      }
      if (this.isWaiting(range)) {
        style.backgroundColor = this.fullColor
        style.opacity = 0.3
      }
      if (!this.isFull(range) && this.isSet(range)) {
        style.backgroundColor = this.setColor
        this.readonly && (style.opacity = 0.3)
      }
      if (this.isPreserve(range)) {
        style.backgroundColor = this.color
      }
      return style
    },
    getAngleStyle(range) {
      const style = {}
      if (this.isSet(range)) {
        style.backgroundColor = this.setColor
      }
      return style
    },
    onClick(range) {
      if (this.readonly || !range.gear || range.min <= this.value) {
        return
      }
      this.triggerChange(range.gear)
    },
    onTouchMove(e) {
      if (!this.swipable || this.readonly) {
        return
      }
      const touch = e.changedTouches[0]
      const gear = this.getGearByPosition(touch.screenX)
      if (gear) {
        this.triggerChange(gear)
      }
    },
    getGearByPosition(screenX) {
      this.sx = screenX
      for (const rect of this.rects) {
        const left = rect.left - this.offset
        const right = rect.dis + this.offset
        if (screenX >= left && screenX <= right && rect.min > this.value) {
          return rect.gear
        }
      }
      return NaN
    },
    triggerChange(gear) {
      this.$emit('change', gear)
    }
  }
}
</script>

<style scoped>
.dof-gear {
  flex-direction: row;
  align-items: flex-start;
}
.dof-gear-gap {
  flex: 1;
  height: 1px;
}
.dof-gear-item {
  flex-direction: column;
  align-items: center;
}
.dof-gear-item-anchor {
  width: 40px;
  height: 20px;
  flex-direction: column;
  align-items: center;
  overflow: hidden;
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
}
.dof-gear-item-anchor-angle {
  width: 28.2842712474619px;
  height: 28.2842712474619px;
  transform-origin: center;
  transform: translateY(-14.14213562373095px) rotateZ(45deg);
}
.dof-gear-item-track {
  position: relative;
}
.dof-gear-item-bar {
  position: absolute;
  bottom: 0;
}
.dof-gear-item-gear {
  margin-top: 16px;
  font-size: 24px;
  font-family: Helvetica;
  max-lines: 1;
  text-overflow: ellipsis;
}
</style>
