<template>
  <div
    class="nv-progress"
    :class="{ reversed: reversed }"
    :style="{ minWidth: `${radius * 2}px`, minHeight: `${radius * 2}px` }"
  >
    <svg
      class="nv-progress__circle"
      :width="radius * 2"
      :height="radius * 2"
      :style="{
        transform: `scaleY(${reversed ? -1 : 1})`,
        top: `calc(50% - ${radius}px)`,
        left: `calc(50% - ${radius}px)`,
      }"
    >
      <linearGradient :id="`bgColor${uid}`" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0%" :stop-color="backgroundColor"></stop>
        <stop
          offset="100%"
          :stop-color="backgroundColorGradientTo || backgroundColor"
        ></stop>
      </linearGradient>
      <circle
        class="nv-progress__background"
        cx="50%"
        cy="50%"
        :r="`calc(50% - ${thickness / 2}px)`"
        :class="backgroundColor ? null : 'stroke-gray-200'"
        :stroke="`url(#bgColor${uid})`"
        :stroke-width="thickness"
        fill="none"
      />
    </svg>
    <svg
      ref="value"
      class="nv-progress__circle"
      :class="{ indeterminate: indeterminate }"
      :width="radius * 2"
      :height="radius * 2"
      :style="{
        transform: `rotate(${rotate - 90}deg) scaleY(${reversed ? -1 : 1})`,
        top: `calc(50% - ${radius}px)`,
        left: `calc(50% - ${radius}px)`,
      }"
    >
      <linearGradient :id="`valueColor${uid}`" x1="0" y1="0" x2="1" y2="1">
        <stop offset="0%" :stop-color="color" />
        <stop offset="100%" :stop-color="colorGradientTo ?? color" />
      </linearGradient>
      <circle
        class="nv-progress__buffer"
        cx="50%"
        cy="50%"
        :r="`calc(50% - ${thickness / 2}px)`"
        :stroke-width="thickness"
        :class="color ? null : 'stroke-primary'"
        :stroke="`url(#valueColor${uid})`"
        :stroke-dasharray="`${bufferWidth * length} 999999`"
        :stroke-linecap="rounded ? 'round' : 'butt'"
      />
      <circle
        class="nv-progress__value"
        :class="color ? null : 'stroke-primary'"
        cx="50%"
        cy="50%"
        :r="`calc(50% - ${thickness / 2}px)`"
        :stroke-width="thickness"
        :stroke="`url(#valueColor${uid})`"
        :stroke-dasharray="`${
          (indeterminate ? 0 : valueWidth) * length
        } 999999`"
        :stroke-linecap="rounded ? 'round' : 'butt'"
      />
    </svg>
    <div class="nv-progress__slot"><slot /></div>
  </div>
</template>

<script>
export default {
  name: "NvProgressCircular",
  props: {
    backgroundColor: { type: String, default: "" },
    backgroundColorGradientTo: { type: String, default: undefined },
    buffer: { type: Number, default: 0 },
    color: { type: String, default: "" },
    colorGradientTo: { type: String, default: undefined },
    indeterminate: Boolean,
    radius: { type: Number, default: 30 },
    thickness: { type: Number, default: 4 },
    total: { type: Number, default: 100 },
    value: { type: Number, default: 0 },
    rotate: { type: Number, default: 0 },
    reversed: Boolean,
    rounded: Boolean,
  },

  data: () => {
    return { length: 0, uid: null };
  },

  computed: {
    bufferWidth() {
      return Math.min(1, this.buffer / this.total);
    },
    valueWidth() {
      return Math.min(1, this.value / this.total);
    },
  },
  created() {
    this.uid = Math.random();
  },
  mounted() {
    this.length = 2 * Math.PI * (this.radius - this.thickness / 2);
  },
};
</script>

<style lang="scss" scoped>
.nv-progress {
  @apply flex items-center justify-center relative;

  &__circle {
    @apply absolute top-0 left-0;
  }

  &__background {
    @apply absolute top-0 left-0;
  }
  &__buffer {
    @apply absolute top-0 left-0 fill-transparent opacity-30;
  }
  &__value {
    @apply absolute top-0 left-0 fill-transparent;
  }
  &__slot {
    @apply flex flex-wrap items-center justify-center z-10 relative;
  }
}

.indeterminate {
  animation: indeterminate 2s linear infinite;
  .nv-progress__value {
    animation: dasharray 2s linear infinite;
  }
}

.reversed .indeterminate {
  animation: reversed-indeterminate 2s linear infinite;
}

@keyframes indeterminate {
  from {
    transform: rotate(-90deg);
  }

  to {
    transform: rotate(270deg);
  }
}

@keyframes reversed-indeterminate {
  from {
    transform: rotate(90deg);
  }

  to {
    transform: rotate(-270deg);
  }
}

@keyframes dasharray {
  from,
  to {
    stroke-dasharray: 0 999999;
  }
  50% {
    stroke-dasharray: 100% 999999;
  }
}
</style>
