<template>
  <div
    :class="[
      'mm-progress--' + type,
      status ? 'mm-progress__' + status : '',
      {
        'mm-progress--without-text': !showText,
        'mm-progress--text-inside': textInside,
      }
    ]"
    class="mm-progress">
    <div
      v-if="type === 'line'"
      class="mm-progress-bar">
      <div
        :style="{height: strokeWidth + 'px'}"
        class="mm-progress-bar-outer">
        <div
          :style="barStyle"
          class="mm-progress-bar-inner">
          <div
            v-if="showText && textInside"
            class="mm-progress-bar-inner-text">
            <slot name="percentageText" :percentage="percentage">
              {{ percentageText || percentage + '%' }}
            </slot>
          </div>
        </div>
      </div>
    </div>
    <div
      v-else
      :style="{height: width + 'px', width: width + 'px'}">
      <svg viewBox="0 0 100 100">
        <path
          :stroke-width="relativeStrokeWidth"
          :d="trackPath"
          class="mm-progress-circle__track"
          stroke="#e5e9f2"
          fill="none" />
        <path
          :style="circlePathStyle"
          :stroke-width="relativeStrokeWidth"
          :d="trackPath"
          :stroke="stroke"
          class="mm-progress-circle__path"
          stroke-linecap="round"
          fill="none" />
      </svg>
    </div>
    <div
      v-if="showText && !textInside"
      :style="{fontSize: progressTextSize + 'px'}"
      class="mm-progress-text">
      <slot name="percentageText" :percentage="percentage">
        <template v-if="percentageText">
          {{ percentageText }}
        </template>
        <template v-else-if="!status || status === 'active'">
          {{ percentage + '%' }}
        </template>
        <ui-icon
          v-else
          :name="iconClass"
          size="1rem"></ui-icon>
      </slot>
    </div>
  </div>
</template>

<script>
import Icon from "../icon"
import config from "../../managers/config"

config.defaults({
  "Progress.type": "line",
  "Progress.percentage": 0,
  "Progress.strokeWidth": 6,
  "Progress.textInside": false,
  "Progress.width": 126,
  "Progress.showText": true,
  "Progress.color": "",
  "Progress.gapPosition": "top",
})

export default {
  name: "mm-progress",
  components: {
    "ui-icon": Icon,
  },
  props: {
    type: {
      type: String,
      default: () => config.get("Progress.type"),
      validator: val => ["line", "circle"].indexOf(val) > -1,
    },
    percentage: {
      type: Number,
      default: () => config.get("Progress.percentage"),
      required: true,
      validator: val => val >= 0 && val <= 100,
    },
    status: {
      type: String,
    },
    strokeWidth: {
      type: Number,
      default: () => config.get("Progress.strokeWidth"),
    },
    textInside: {
      type: Boolean,
      default: () => config.get("Progress.textInside"),
    },
    width: {
      type: Number,
      default: () => config.get("Progress.width"),
    },
    showText: {
      type: Boolean,
      default: () => config.get("Progress.showText"),
    },
    color: {
      type: String,
      default: () => config.get("Progress.color"),
    },
    gapPosition: {
      type: String,
      default: () => config.get("Progress.gapPosition"),
      validator: val => ["top", "bottom", "left", "right"].indexOf(val) > -1,
    },
    format: {
      type: Function,
      default: () => {},
    },
  },
  computed: {
    barStyle() {
      const style = {}
      style.width = this.percentage + "%"
      style.backgroundColor = this.color
      return style
    },
    relativeStrokeWidth() {
      return ((this.strokeWidth / this.width) * 100).toFixed(1)
    },
    trackPath() {
      const radius = parseInt(50 - parseFloat(this.relativeStrokeWidth) / 2, 10)
      return `M 50 50 m 0 -${radius} a ${radius} ${radius} 0 1 1 0 ${radius *
        2} a ${radius} ${radius} 0 1 1 0 -${radius * 2}`
    },
    perimeter() {
      const radius = 50 - parseFloat(this.relativeStrokeWidth) / 2
      return 2 * Math.PI * radius
    },
    circlePathStyle() {
      const perimeter = this.perimeter
      const position = this.gapPosition
      let angel = 0
      switch (position) {
        case "right":
          angel = 90
          break
        case "bottom":
          angel = 180
          break
        case "left":
          angel = 270
          break
      }
      return {
        strokeDasharray: `${perimeter}px,${perimeter}px`,
        strokeDashoffset: (1 - this.percentage / 100) * perimeter + "px",
        transition: "stroke-dashoffset 0.6s ease 0s, stroke 0.6s ease",
        transform: `rotateZ(${angel}deg)`,
        transformOrigin: "50% 50% 0",
      }
    },
    stroke() {
      let ret
      if (this.color) {
        ret = this.color
      } else {
        switch (this.status) {
          case "success":
            ret = "#13ce66"
            break
          case "exception":
            ret = "#ff4949"
            break
          default:
            ret = "#20a0ff"
        }
      }
      return ret
    },
    iconClass() {
      if (this.type === "line") {
        return this.status === "success" ? "check" : "close"
      } else {
        return this.status === "success" ? "check" : "close"
      }
    },
    progressTextSize() {
      return this.type === "line" ? 12 + this.strokeWidth * 0.4 : this.width * 0.111111 + 8
    },
    percentageText() {
      const percentage = this.percentage
      return this.format(percentage)
    },
  },
}
</script>
