<template>
    <div
        :class="cx('root')"
        role="progressbar"
        :aria-valuemin="min"
        :aria-valuemax="max"
        :aria-valuenow="isDeterminate ? clampedValue : undefined"
        :data-state="determinateState"
        :data-value="isDeterminate ? clampedValue : undefined"
        v-bind="ptmi('root')"
    >
        <svg :class="cx('circle')" viewBox="0 0 100 100" :style="svgStyle" v-bind="ptm('circle')">
            <circle :class="cx('circleTrack')" cx="50" cy="50" :r="radius" fill="none" :stroke-width="strokeWidth" v-bind="ptm('circleTrack')" />
            <circle
                :class="cx('circleRange')"
                cx="50"
                cy="50"
                :r="radius"
                fill="none"
                :stroke-width="strokeWidth"
                :stroke-dasharray="isDeterminate ? circumference : undefined"
                :stroke-dashoffset="isDeterminate ? dashOffset : undefined"
                v-bind="ptm('circleRange')"
            />
            <text v-if="isDeterminate" :class="cx('value')" x="50" y="50" text-anchor="middle" dominant-baseline="central" v-bind="ptm('value')">
                <slot :value="clampedValue" :percent="roundedPercent">{{ roundedPercent }}%</slot>
            </text>
        </svg>
    </div>
</template>

<script>
import BaseProgressSpinner from './BaseProgressSpinner.vue';

export default {
    name: 'ProgressSpinner',
    extends: BaseProgressSpinner,
    inheritAttrs: false,
    computed: {
        isDeterminate() {
            return Number.isFinite(this.value);
        },
        determinateState() {
            return this.isDeterminate ? 'determinate' : 'indeterminate';
        },
        validRange() {
            return Number.isFinite(this.min) && Number.isFinite(this.max) && this.max > this.min;
        },
        clampedValue() {
            if (!this.isDeterminate) {
                return 0;
            }

            if (!this.validRange) {
                return Number.isFinite(this.min) ? this.min : 0;
            }

            const value = Number.isFinite(this.value) ? this.value : this.min;

            return Math.min(Math.max(value, this.min), this.max);
        },
        percent() {
            return !this.isDeterminate || !this.validRange ? 0 : ((this.clampedValue - this.min) / (this.max - this.min)) * 100;
        },
        roundedPercent() {
            return Math.round(this.percent);
        },
        radius() {
            return (100 - this.strokeWidth) / 2;
        },
        circumference() {
            return 2 * Math.PI * this.radius;
        },
        dashOffset() {
            return this.circumference - (this.percent / 100) * this.circumference;
        },
        svgStyle() {
            return {
                'animation-duration': this.animationDuration
            };
        }
    }
};
</script>
