<template lang="html">
  <svg :style="styles.svg">
    <defs>
      <slot name="gradient-outer">
        <linearGradient :id="`gradient-outer-${_uid}`"
                        x1="0%" y1="0%"
                        x2="0%" y2="100%"
                        spreadMethod="pad"
        >
          <template v-for="(s,index) in outerBackgroundColors">
            <stop :key="index" :offset="`${s.offset}%`" :stop-color="`${s.stopColor}`" />
          </template>
        </linearGradient>
      </slot>
      <slot v-if="showValue && !small" name="gradient-inner">
        <linearGradient :id="`gradient-inner-${_uid}`"
                        x1="0%" y1="0%"
                        x2="0%" y2="100%"
                        spreadMethod="pad"
        >
          <template v-for="(s,index) in innerBackgroundColors">
            <stop :key="index" :offset="`${s.offset}%`" :stop-color="`${s.stopColor}`" />
          </template>
        </linearGradient>
      </slot>
    </defs>
    <circle :style="styles.circle" :class="outerCircleClass" :cx="cx" :cy="cy" :r="r" />
    <path :style="styles.path1" :class="pathClass" :d="d1" />
    <template v-if="showValue && !small">
      <circle :style="styles.innerCircle" :class="innerCircleClass" :cx="cx" :cy="cy" :r="r/2" />
      <text x="50%" y="50%" dominant-baseline="middle" text-anchor="middle" :style="styles.innerText" :class="innerTextClass">
        {{ percent ? valueAsPercent : value }}
      </text>
    </template>
  </svg>
</template>

<script>
export default {
  props: {
    radius: { type: Number, default: null },
    value: { type: Number, default: 0 },
    maxValue: { type: Number, default: 100 },
    outerBorderWidth: { type: Number, default: null },
    outerBackgroundColors: {type: Array,
      default: () => [
        {offset: '0', stopColor: '#39f'},
        {offset: '100', stopColor: '#00f'}
      ]
    },
    outerCircleClass: { type: String, default: null },
    pathClass: { type: String, default: null },
    fillColor: { type: String, default: '#f1f1f1' },
    innerBorderColor: { type: String, default: '#f1f1f1' },
    innerBorderWidth: { type: Number, default: 3 },
    innerBackgroundColors: {type: Array,
      default: () => [
        {offset: '0', stopColor: '#2268ff'},
        {offset: '100', stopColor: '#0d29ff'}
      ]
    },
    innerCircleClass: { type: String, default: null },
    innerTextClass: { type: String, default: null },
    innerTextColor: { type: String, default: '#f1f1f1' },
    innerFontSize: { type: String, default: '0.68rem' },
    innerFontWeight: { type: String, default: 'bold' },
    showValue: { type: Boolean, default: true },
    percent: { type: Boolean, default: true },
    small: { type: Boolean, default: false }
  },
  data: () => ({
  }),
  computed: {
    cx() {
      return this.r + this.obw
    },
    cy() {
      return this.r + this.obw
    },
    r() {
      return this.radius || (this.small ? 10 : 25)
    },
    obw() {
      return this.outerBorderWidth || (this.small ? 1 : 3)
    },
    d1() {
      const coords = this.coords(this.toRadians(this.valueAsPercent))
      return `M${this.cx},${this.cy} L${this.cx},${this.obw}${this.value > 50 ? ` A${this.r},${this.r} 1 0,1 ${this.cx},${this.cx + this.r} ` : ``}A${this.r},${this.r} 1 0,1 ${coords.x},${coords.y} z`
    },
    styles() {
      return {
        circle: `fill: ${this.fillColor}; stroke: url(#gradient-outer-${this._uid}); stroke-width: ${this.obw};`,
        innerCircle: `fill: url(#gradient-inner-${this._uid}); stroke: ${this.innerBorderColor}; stroke-width: ${this.innerBorderWidth};`,
        innerText: `fill: ${this.innerTextColor}; stroke: none; font-size: ${this.innerFontSize}; font-weight: ${this.innerFontWeight};`,
        path1: `fill: url(#gradient-outer-${this._uid});`,
        svg: `width: ${2 * (this.r + this.obw)}px;height: ${2 * (this.r + this.obw)}px;`
      }
    },
    valueAsPercent() {
      return this.value * 100 / this.maxValue
    }
  },
  methods: {
    toRadians(value) {
      // 1 percent to radian = 0.06283 radian
      // start at 270° ie 3PI/2
      const radians = (3 * Math.PI / 2) + (Math.min(Math.ceil(this.value), 100) * 0.06283)
      return radians
    },
    coords(angle) {
      const x = this.cx + this.r * Math.cos(angle)
      const y = this.cy + this.r * Math.sin(angle)
      return {x, y}
    }
  }
}
</script>
