<template>
  <div
    class="bx-rate-wrapper"
    :style="{
      display: position === 'right' ? 'inline-block' : 'block'
    }"
    >
    <div 
      v-if="position === 'right'"
      class="bx-rate-content bx-rate-right" 
      >
      <label
        class="bx-rate-label"
        v-if="rateLabel"
        >
        {{ rateLabel }}
      </label>

      <div class="bx-rate-star-wrapper">
        <ul 
          class="bx-rate-star"
          @touchstart="touchstartRate"
          @touchmove="touchmoveRate"
          @touchend="touchendRate"
          @touchcancel="touchendRate"
          :style="{
            width: starWidth
          }"
          >
          <li 
            class="bx-rate-star-li" 
            v-for="n in count"
            :data-rate-value="n"
            :key="n"
            @click="setCurrentValue(n)"
            >
            <span class="bx-rate-star-li-wrapper">
              <bxs-icon 
                name="star-solid"
                class="bx-rate-star-li-icon" 
                :class="n < Math.ceil(currentValue) ? 'bx-rate-star-li-icon--opacity' : ''"
                :style="{
                  fontSize: starSize || iconSize,
                  color: voidColor
                }"
                />

              <span 
                class="bx-rate-star-li-clipper"
                v-if="n <= Math.ceil(currentValue)" 
                :style="{
                  width: getClipperWidth(n)
                }"
                >
                <bxs-icon 
                  name="star-solid"
                  class="bx-rate-star-li-icon" 
                  :style="{
                    fontSize: starSize || iconSize,
                    color: color
                  }"
                  />
              </span>
            </span>
          </li>
        </ul>
      </div>

      <span
        class="bx-rate-number"
        v-if="showRateNum"
        :style="{
          color: currentValue === null ? '#ccc' : color
        }"
        >
        {{ currentValue === null ? '0.0' : (currentValue * 1).toFixed(1) }}
      </span>

      <span 
        class="bx-rate-text" 
        v-if="textList && textList.length && currentValue"
        >
        {{ getRateText() }}
      </span>
    </div>


    <div 
      v-else
      class="bx-rate-content bx-rate-bottom" 
      >
      <header
        class="bx-rate-header"
        v-if="showRateNum"
        :style="{
          color: currentValue === null ? '#ccc' : color
        }"
        >
        {{ currentValue === null ? '0.0' : (currentValue * 1).toFixed(1) }}分
      </header>

      <ul 
        class="bx-rate-star"
        @touchstart="touchstartRate"
        @touchmove="touchmoveRate"
        @touchend="touchendRate"
        @touchcancel="touchendRate"
        >
        <li 
          class="bx-rate-star-li" 
          v-for="n in count"
          :data-rate-value="n"
          :key="n"
          @click="setCurrentValue(n)"
          >
          <bxs-icon 
            name="star-solid"
            class="bx-rate-star-li-icon" 
            :class="n < Math.ceil(currentValue) ? 'bx-rate-star-li-icon--opacity' : ''"
            :style="{
              fontSize: iconSize,
              color: voidColor
            }"
            />
          <span 
            class="bx-rate-star-li-clipper"
            v-if="n <= Math.ceil(currentValue)" 
            :style="{
              width: getClipperWidth(n)
            }"
            >
            <bxs-icon 
              name="star-solid"
              class="bx-rate-star-li-icon" 
              :style="{
                fontSize: iconSize,
                color: color
              }"
              />
          </span>
        </li>
      </ul>

      <p 
        class="bx-rate-text" 
        v-if="textList && textList.length"
        :style="{
          color: currentValue === null ? '#999' : color,
          fontSize: txFontSize
        }"
        >
        {{ getRateText() }}
      </p>

      <ul
        class="bx-rate-tag"
        v-if="tagList"
        >
        <li
          class="bx-rate-tag-li"
          v-for="(t, ti) in (tagList.constructor === Array ? tagList : defaultTagList)"
          :key="t"
          :style="{
            'color': ti === currentTag ? color : '#333',
            'border-color': ti === currentTag ? color : '#ccc'
          }"
          @click="setCurrentTag(ti)"
          >
          {{ t }}
        </li>
      </ul>
    </div>
  </div>
</template>
<script>
import { create } from '../utils'
import Icon from '../icon/index'

const count = 5
export default create({
  name: 'rate',
  data() {
    let iconSize
    if (this.size) {
      if (Number.isNaN(Number(this.size))) {
        iconSize = this.size
      } else {
        iconSize = `${this.size}px`
      }
    } else {
      iconSize = this.position === 'right' ? '18px' : '30px'
    }
    return {
      currentValue: this.value,
      iconSize,
      count,
      beforeTouchValue: this.value,
      currentTag: this.tag,
      defaultTagList: ['服务好', '速度快', '效率高'],
    }
  },
  props: {
    value: {
      type: Number,
      default: null,
      validator(value) {
        return value <= count
      },
    },
    textList: {
      type: Array,
      default() {
        return ['非常差', '差', '一般', '好', '非常好']
      },
    },
    size: {
      type: String,
      default: null,
    },
    position: {
      type: String,
      default: 'bottom',
      validator(value) {
        // 这个值必须匹配下列字符串中的一个
        return ['bottom', 'right'].indexOf(value) !== -1
      },
    },
    color: {
      type: String,
      default: '#FF9224',
    },
    voidColor: {
      type: String,
      default: '#E5E5E5',
    },
    readonly: {
      type: Boolean,
      default: false,
    },
    tag: {
      type: Number,
      default: null,
    },
    tagList: {
      type: [Boolean, Array],
    },
    starWidth: {
      type: String,
      default: '114px',
    },
    starSize: {
      type: String,
      required: false,
      default: '',
    },
    rateLabel: {
      type: String,
      required: '',
    },
    showRateNum: {
      type: Boolean,
      required: false,
      default: true,
    },
  },
  methods: {
    setCurrentValue(value) {
      if (!this.readonly && this.currentValue !== value) {
        this.currentValue = value
        this.$emit('change', this.currentValue, this.currentTag)
      }
    },
    setCurrentTag(tag) {
      if (!this.readonly) {
        if (this.currentTag !== tag) {
          this.currentTag = tag
        } else {
          this.currentTag = null
        }
        this.$emit('change', this.currentValue, this.currentTag)
      }
    },
    touchstartRate() {
      this.beforeTouchValue = this.currentValue
    },
    touchmoveRate(event) {
      if (document.elementFromPoint) {
        const getTouchElement = document.elementFromPoint(
          event.touches[0].clientX,
          event.touches[0].clientY,
        )
        if (
          getTouchElement &&
          getTouchElement.dataset &&
          getTouchElement.dataset.rateValue !== undefined
        ) {
          if (
            !this.readonly &&
            this.currentValue !== getTouchElement.dataset.rateValue
          ) {
            this.currentValue = getTouchElement.dataset.rateValue
          }
        }
      } else {
        const getTouchElement = event.currentTarget
        if (getTouchElement && event.touches[0]) {
          const distanceX =
            event.touches[0].clientX - getTouchElement.offsetLeft
          let touchRateValue = Math.ceil(
            distanceX / (getTouchElement.offsetWidth / this.count),
          )
          if (touchRateValue < 1) {
            touchRateValue = 1
          }
          if (touchRateValue > this.count) {
            touchRateValue = this.count
          }
          if (!this.readonly && this.currentValue !== touchRateValue) {
            this.currentValue = touchRateValue
          }
        }
      }
    },
    touchendRate() {
      if (!this.readonly && this.currentValue !== this.beforeTouchValue) {
        this.$emit('change', this.currentValue, this.currentTag)
      }
    },
    // 星星裁切框的宽度
    getClipperWidth(n) {
      return this.currentValue % 1 && n > this.currentValue
        ? `${(this.currentValue % 1) * 100}%`
        : '100%'
    },
    // 评分文案
    getRateText() {
      return (
        this.textList[
          parseInt(
            (this.currentValue > count ? count : this.currentValue) - 1,
            10,
          )
        ] || '请选择评分'
      )
    },
  },
  components: {
    [Icon.name]: Icon,
  },
  computed: {
    txFontSize() {
      return (
        parseFloat(this.iconSize) * (13 / 30) +
        this.iconSize.replace(/(\d|\.)+/g, '')
      )
    },
  },
})
</script>
<style>
@import './index.css';
</style>
