<script setup lang="ts">
import type { ThemeType } from '@bagelink/vue'
import type { SizeUnit, SizeType } from '../types/BtnOptions'
import { computed } from 'vue'
import { standardSize } from '../utils/sizeParsing'

type LoadingType = 'ring' | 'ellipsis' | 'bar'

const { type: theme = 'ring', size = 50, thickness, duration = 1.2, color, progress } = defineProps<{
	size?: SizeUnit | SizeType
	thickness?: SizeUnit
	duration?: number | string
	type?: LoadingType
	color?: ThemeType | string
	progress?: number
}>()

// Computed Values
const computedSize = computed(() => standardSize(size))
const animationDuration = computed(() => `${duration}s`)
const computedBorder = computed(() => {
	const borderValue = thickness ?? Math.max(Number.parseInt(computedSize.value, 10) / 9, 2)
	return standardSize(borderValue)
})

const computedColor = computed(() => {
	if (!color) return 'var(--bgl-black)'
	if (color.startsWith('#') || color.startsWith('rgb') || color.startsWith('var(')) {
		return color // Custom color string
	}
	return `var(--bgl-${color})` // Convert theme color to CSS variable
})

// SVG progress calculations
const svgStrokeWidth = computed(() => {
	const borderNumeric = Number.parseFloat(computedBorder.value)
	const sizeNumeric = Number.parseFloat(computedSize.value)
	return Math.round((borderNumeric / sizeNumeric) * 100) * 0.9
})
const svgRadius = computed(() => 50 - (svgStrokeWidth.value / 2))
const svgCircumference = computed(() => Math.PI * 2 * svgRadius.value)
</script>

<template>
	<div
		class="flex-center loading-container" :style="{ '--progress': progress }"
		:class="{ progress: progress !== undefined }"
	>
		<!-- Bar Theme -->
		<template v-if="theme === 'bar'">
			<slot />
			<div class="lds-bar" :style="{ animationDuration, color: computedColor }" />
		</template>

		<!-- Ellipsis Theme -->
		<template v-if="theme === 'ellipsis'">
			<slot />
			<div class="lds-ellipsis" :style="{ '--size': computedSize }">
				<div v-for="n in 4" :key="n" :style="{ 'color': computedColor, '--size': computedSize }" />
			</div>
		</template>

		<!-- Ring Theme -->
		<div v-if="theme === 'ring'" class="lds-ring" :style="{ '--size': computedSize, '--thickness': computedBorder }">
			<template v-if="progress !== undefined">
				<svg :width="computedSize" :height="computedSize" viewBox="0 0 100 100">
					<circle
						cx="50" cy="50" :r="svgRadius" fill="none" :stroke="computedColor"
						:stroke-width="svgStrokeWidth" stroke-opacity="0.2"
					/>
					<circle
						cx="50" cy="50" :r="svgRadius" fill="none" :stroke="computedColor"
						:stroke-width="svgStrokeWidth" stroke-linecap="round"
						:stroke-dasharray="`${(progress / 100) * svgCircumference} ${svgCircumference}`"
						transform="rotate(-90 50 50)"
					/>
				</svg>
			</template>
			<div
				v-for="n in 4" v-else :key="n" class="ring-segment" :style="{
					'color': computedColor,
					'width': computedSize,
					'height': computedSize,
					'borderWidth': computedBorder,
					'--animation-duration': animationDuration,
					'--size': computedSize,
					'--thickness': computedBorder,
				}"
			/>
			<div class="slot-content">
				<slot />
			</div>
		</div>
	</div>
</template>

<style scoped>
/* Loading Container */
.loading-container {
  flex-direction: column;
  gap: 0.5rem;
}

/* Bar Theme */
.lds-bar {
  height: var(--thickness, 4px);
  width: 100%;
  --c: no-repeat linear-gradient(currentColor 0 0);
  background: var(--c), var(--c), #ddd;
  background-size: 60% 100%;
  animation: bar-animation 3s infinite ease-in-out;
}

.progress .lds-bar {
  background-size: calc(var(--progress) * 1%) 100%;
  transition: background-size 0.2s ease;
  background-position: 0 0;
  animation: none;
}

@keyframes bar-animation {
  0% {
    background-position: -150% 0, -150% 0
  }

  66% {
    background-position: 250% 0, -150% 0
  }

  100% {
    background-position: 250% 0, 250% 0
  }
}

/* Ring Theme */
.lds-ring,
.lds-ring .ring-segment {
  box-sizing: border-box;
}

.lds-ring {
  position: relative;
  width: var(--size);
  height: var(--size);
  transform: translate(calc(var(--thickness) * -1), calc(var(--thickness) * -1));
  direction: ltr;
}

.lds-ring .slot-content {
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
}

.progress .lds-ring svg {
  position: absolute;
  top: var(--thickness);
  left: var(--thickness);
}

.lds-ring .ring-segment {
  display: block;
  position: absolute;
  width: calc(var(--size) / 1.25);
  height: calc(var(--size) / 1.25);
  margin: var(--thickness);
  border: var(--thickness) solid currentColor;
  border-radius: 50%;
  animation: lds-ring var(--animation-duration) cubic-bezier(0.5, 0, 0.5, 1) infinite;
  border-color: currentColor transparent transparent transparent;
}

.lds-ring .ring-segment:nth-child(1) {
  animation-delay: calc(var(--animation-duration) * -0.38);
}

.lds-ring .ring-segment:nth-child(2) {
  animation-delay: calc(var(--animation-duration) / -4);
}

.lds-ring .ring-segment:nth-child(3) {
  animation-delay: calc(var(--animation-duration) / -8);
}

@keyframes lds-ring {
  0% {
    transform: rotate(0deg);
  }

  100% {
    transform: rotate(360deg);
  }
}

/* Ellipsis Theme */
.lds-ellipsis,
.lds-ellipsis div {
  box-sizing: border-box;
}

.lds-ellipsis {
  display: inline-block;
  position: relative;
  width: var(--size);
  height: var(--size);
}

.lds-ellipsis div {
  position: absolute;
  top: calc(var(--size) / 2 - calc(var(--size) / 10));
  width: calc(var(--size) / 5);
  height: calc(var(--size) / 5);
  border-radius: 50%;
  background: currentColor;
  animation-timing-function: cubic-bezier(0, 1, 1, 0);
}

.lds-ellipsis div:nth-child(1) {
  left: calc(var(--size) / 10);
  animation: lds-ellipsis1 0.6s infinite;
}

.lds-ellipsis div:nth-child(2) {
  left: calc(var(--size) / 10);
  animation: lds-ellipsis2 0.6s infinite;
}

.lds-ellipsis div:nth-child(3) {
  left: calc(var(--size) / 2.5);
  animation: lds-ellipsis2 0.6s infinite;
}

.lds-ellipsis div:nth-child(4) {
  left: calc(var(--size) / 1.42);
  animation: lds-ellipsis3 0.6s infinite;
}

@keyframes lds-ellipsis1 {
  0% {
    transform: scale(0);
  }

  100% {
    transform: scale(1);
  }
}

@keyframes lds-ellipsis3 {
  0% {
    transform: scale(1);
  }

  100% {
    transform: scale(0);
  }
}

@keyframes lds-ellipsis2 {
  0% {
    transform: translate(0, 0);
  }

  100% {
    transform: translate(calc(var(--size) / 3.33), 0);
  }
}
</style>
