<template>
  <span ref="wrapper" class="rating" @click="handleClick" @mousemove="handleMousemove" @mouseleave="handleMouseleave">
    <span class="set empty-set">
      <app-iconic-icon v-for="i in starCount" :key="i" icon="star-empty" size="md"></app-iconic-icon>
    </span>
    <span class="set filled-set" :style="filledStyle">
      <app-iconic-icon v-for="i in starCount" :key="i" icon="star" size="md"></app-iconic-icon>
    </span>
  </span>
</template>

<script setup>

import { computed, ref, useTemplateRef } from "vue";

const emit = defineEmits(["update:modelValue"]);

const props = defineProps({
  starCount: {
    required: false,
    type: Number,
    default: 5
  },

  readonly: {
    required: false,
    type: Boolean,
    default: false
  },

  step: {
    required: false,
    type: Number,
    default: 0.5
  },

  modelValue: {
    required: false,
    type: Number,
    default: 0
  }
});

const temporaryValue = ref(null);
const ratingPercent = computed(() => ((props.modelValue || 0) / props.starCount) * 100.0);
const wrapperEl = useTemplateRef("wrapper");

const temporaryPercent = computed(() => {
  if (temporaryValue.value !== null) {
    return (temporaryValue.value / props.starCount) * 100.0;
  } else {
    return null;
  }
});

const filledStyle = computed(() => {
  const width = temporaryPercent.value || ratingPercent.value;
  return {
    width: width + "%"
  };
});

function handleClick(evt) {
  if (temporaryValue.value !== null) {
    emit("update:modelValue", temporaryValue.value);
  }
}

function handleMousemove(evt) {
  if (props.readonly) {
    return;
  }

  const wrapperBox = wrapperEl.value.getBoundingClientRect();
  const wrapperWidth = wrapperBox.right - wrapperBox.left;
  const mousePosition = evt.clientX;

  if (mousePosition > wrapperBox.left && mousePosition < wrapperBox.right) {
    const filledRatio = ((mousePosition - wrapperBox.left) / wrapperWidth);

    const totalSteps = props.starCount / props.step;
    const filledSteps = Math.round(totalSteps * filledRatio);

    temporaryValue.value = filledSteps * props.step;
  }
}

function handleMouseleave(evt) {
  temporaryValue.value = null;
}

</script>

<style lang="scss" scoped>

  @use "bulma/sass/utilities" as bulma;

  span.rating {
    position: relative;
    display: inline-block;

    .set {
      white-space: nowrap;

      svg.iconic {
        width: 1.5em;
        height: 1.5em;
      }
    }

    .empty-set {
      color: gray;
    }

    .filled-set {
      color: bulma.$yellow;
      position: absolute;
      top: 0;
      left: 0;
      overflow-x: hidden;
    }
  }

</style>