<script lang="ts" setup>
import { vue } from '@factor/api'

const props = defineProps({
  loading: { type: [Boolean, String], default: false },
  btn: {
    type: String as vue.PropType<
      | 'danger'
      | 'caution'
      | 'success'
      | 'primary'
      | 'default'
      | 'theme'
      | 'naked'
      | string
    >,
    default: '',
  },
  size: {
    type: String as vue.PropType<'xs' | 'sm' | 'md' | 'lg' | 'xl'>,
    default: '',
  },
  to: { type: String, default: '' },
  href: { type: String, default: '' },
  disabled: { type: Boolean, default: false },
  format: {
    type: String as vue.PropType<'block' | 'spread' | 'inline'>,
    default: 'inline',
  },
  rounded: {
    type: String as vue.PropType<'md' | 'lg' | 'full'>,
    default: '',
  },
  wrapClass: { type: String, default: '' },
  animate: { type: Boolean, default: false },
})

const animateSelected = vue.ref()
function onClick() {
  animateSelected.value = true
  setTimeout(() => {
    animateSelected.value = false
  }, 1000)
}

const btnClass = vue.computed(() => {
  let out
    = 'border relative max-w-full select-none items-center font-sans shadow-sm ring-offset-2 hover:shadow-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 active:shadow-none '
  if (props.btn === 'danger') {
    out
      += 'bg-danger-500 hover:bg-danger-400 focus-visible:outline-danger-500 text-danger-0 border-danger-500'
  }
  else if (props.btn === 'caution') {
    out
      += 'bg-caution-500 hover:bg-caution-400 focus-visible:outline-caution-500 text-caution-0 border-caution-500'
  }
  else if (props.btn === 'primary') {
    out
      += 'bg-primary-600 hover:bg-primary-500 focus-visible:outline-primary-600 text-primary-0 border-primary-600'
  }
  else if (props.btn === 'success') {
    out
      += 'bg-success-500 hover:bg-success-400 focus-visible:outline-success-500 text-success-0 border-success-500'
  }
  else if (props.btn === 'theme') {
    out
      += 'bg-theme-500 hover:bg-theme-400 focus-visible:outline-theme-500 text-theme-0 border-theme-500'
  }
  else if (props.btn === 'naked') {
    out += ''
  }
  else {
    out += 'bg-theme-0 hover:bg-theme-100 border-theme-300 text-theme-800'
  }

  let roundClass = props.size === 'xl' ? 'rounded-xl' : 'rounded-lg'

  if (props.rounded === 'full')
    roundClass = 'rounded-full'
  else if (props.rounded === 'md')
    roundClass = 'rounded-md'
  else if (props.rounded === 'lg')
    roundClass = 'rounded-xl'

  let sizeClasses = 'px-input-x-2 py-input-y text-[.85em]'
  if (props.size === 'md')
    sizeClasses = 'px-2.5 py-1.5 text-xs'
  else if (props.size === 'sm')
    sizeClasses = 'px-2.5 py-1 text-[.85em]'
  else if (props.size === 'xs')
    sizeClasses = 'px-2.5 py-1 text-xs'
  else if (props.size === 'lg')
    sizeClasses = 'px-4 py-2 text-base'
  else if (props.size === 'xl')
    sizeClasses = 'px-6 py-2.5 sm:text-base md:text-lg'

  let formatClasses = 'inline-flex'
  if (props.format === 'block')
    formatClasses = 'flex justify-center w-full'
  else if (props.format === 'spread')
    formatClasses = 'flex justify-between w-full'

  out += ` ${sizeClasses} ${formatClasses} ${roundClass}`

  if (props.disabled)
    out = `${out} opacity-40 cursor-not-allowed`

  return out
})
</script>

<template>
  <component
    :is="
      to || (href && !href?.includes('http'))
        ? 'router-link'
        : href
          ? 'a'
          : 'button'
    "
    :to="to || href"
    class="relative max-w-full select-none items-center font-sans font-semibold shadow-sm ring-offset-2 hover:shadow-md focus:outline-none active:shadow-none"
    :class="[btnClass, animateSelected && animate ? 'animate-selected' : '']"
    :href="href"
    @click="onClick()"
  >
    <div
      v-if="loading"
      class="absolute left-0 flex w-full items-center justify-center"
    >
      <svg
        class="h-4 w-4 animate-spin"
        xmlns="http://www.w3.org/2000/svg"
        fill="none"
        viewBox="0 0 24 24"
      >
        <circle
          class="opacity-25"
          cx="12"
          cy="12"
          r="10"
          stroke="currentColor"
          stroke-width="4"
        />
        <path
          class="opacity-75"
          fill="currentColor"
          d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
        />
      </svg>
    </div>
    <span
      class="flex w-full min-w-0 items-center whitespace-nowrap"
      :class="[
        loading ? 'opacity-0' : '',
        wrapClass,
        format === 'spread' ? '' : 'justify-center',
      ]"
    >
      <slot />
    </span>
  </component>
</template>

<style>
.animate-selected {
  animation: clickButton 0.3s linear forwards;
}

@keyframes clickButton {
  0% {
    opacity: 0.2;
  }
  25% {
    opacity: 1;
  }
  50% {
    opacity: 0.2;
  }
  100% {
    opacity: 1;
  }
}
</style>
