<script setup lang="ts">
import { computed, PropType } from "vue";

const props = defineProps({
  points: {
    type: Array as PropType<number[]>,
    default: () => [],
  },
  width: {
    type: Number,
    default: 280,
  },
  height: {
    type: Number,
    default: 14,
  },
  padding: {
    type: Number,
    default: 4,
  },
});

const validPoints = computed(() =>
  (props.points || [])
    .map((value) => (Number.isFinite(value) ? Number(value) : null))
    .filter((value): value is number => value !== null)
);

const pointRange = computed(() => {
  const points = validPoints.value;
  if (points.length === 0) {
    return { min: 0, max: 1 };
  }
  const min = Math.min(...points);
  const max = Math.max(...points);
  return { min, max };
});

const svgPoints = computed(() => {
  const points = validPoints.value;
  const { min, max } = pointRange.value;
  if (points.length === 0) {
    return "";
  }
  const delta = max - min || 1;
  const availableWidth = props.width - props.padding * 2;
  const availableHeight = props.height - props.padding * 2;
  const step = points.length > 1 ? availableWidth / (points.length - 1) : 0;
  return points
    .map((value, index) => {
      const x = props.padding + step * index;
      const normalized = (value - min) / delta;
      const y = props.padding + availableHeight * (1 - normalized);
      return `${x},${y}`;
    })
    .join(" ");
});

const hasPoints = computed(() => validPoints.value.length > 1);
</script>

<template>
  <div class="mini-sparkline">
    <svg
      :width="width"
      :height="height"
      :viewBox="`0 0 ${width} ${height}`"
      role="presentation"
      aria-hidden="true"
    >
      <polyline
        v-if="hasPoints"
        :points="svgPoints"
        class="sparkline-polyline"
        fill="none"
      />
      <line
        v-else
        :x1="padding"
        :y1="height / 2"
        :x2="width - padding"
        :y2="height / 2"
        class="sparkline-polyline"
      />
    </svg>
  </div>
</template>
