<script setup lang="ts">
import { ref, computed, useSlots, onMounted } from 'vue'

import { type ColorProps, type VariantProps, type DefaultProps, type RaisedProps, color } from '~/composables/color';
import { type WidthProps, width } from '~/composables/width'
import { type AlignmentProps, align } from '~/composables/alignment'

import Loader from '~/components/ui/Loader.vue'

const props = defineProps<{
  thinFont?: true
  lowHeight? : true

  isActive?: boolean
  isLoading?: boolean

  shadow?: boolean
  round?: boolean
  icon?: string

  onClick?: (...args: any[]) => void | Promise<void>

  autofocus? : boolean
  ariaPressed? : true
} & (ColorProps | DefaultProps)
  & VariantProps
  & RaisedProps
  & WidthProps
  & AlignmentProps>()

const slots = useSlots()
const isIconOnly = computed(() => !!props.icon && !slots.default)

const internalLoader = ref(false)
const isLoading = computed(() => props.isLoading || internalLoader.value)

const fontWeight = props.thinFont ? 400 : 900

const button = ref()


const click = async (...args: any[]) => {
  internalLoader.value = true

  try {
    await props.onClick?.(...args)
  } finally {
    internalLoader.value = false
  }
}
onMounted(() => {
  if (props.autofocus) button.value.focus();
})
</script>

<template>
  <button ref="button"
    v-bind="color(props, ['interactive'])(
            width(props, isIconOnly ? ['square'] : ['normalHeight', 'buttonWidth'])(
            align(props, { alignSelf:'start', alignText:'center' })(
            )))"
    class="funkwhale button"
    :aria-pressed="props.ariaPressed"
    :class="{
        'is-loading': isLoading,
        'is-icon-only': isIconOnly,
        'has-icon': !!icon,
        'is-round': round,
        'is-shadow': shadow,
    }"
    @click="click"
  >
    <i v-if="icon" :class="['bi', icon]" />

    <span>
      <slot />
    </span>

    <Loader v-if="isLoading" :container="false" />
  </button>
</template>

<style lang="scss">
.funkwhale {
  &.button {

    // Layout

    --padding: 16px;
    --shift-by: 0.5px;

    position: relative;
    display: inline-flex;
    white-space: nowrap;
    justify-content: space-between;
    align-items: center;

    padding: calc(var(--padding) / 2 - var(--shift-by)) var(--padding) calc(var(--padding) / 2 + var(--shift-by)) var(--padding);
    &.is-icon-only {
      padding: var(--padding);
    }

    // Font

    font-family: $font-main;
    font-weight: v-bind(fontWeight);
    font-size: 14px;

    line-height: 14px;

    // Decoration

    transform: translateX(var(--fw-translate-x)) translateY(var(--fw-translate-y)) scale(var(--fw-scale));
    transition: all .2s ease;

    &.is-shadow {
      box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.2);
    }

    border-radius: var(--fw-border-radius);
    &.is-round {
      border-radius: 100vh;
    }

    // States

    &[disabled] {
      font-weight: normal;
      pointer-events: none;
    }

    &.is-loading {
      @extend :active;

      > span {
        opacity: 0;
      }
    }

    // Content

    > span {
      position: relative;
      top: calc(0px - var(--shift-by));
    }

    // Icon

    i.bi {
      font-size: 18px;
      margin: -2px 0;
      &.large {
        font-size: 32px;
        margin: -8px 0;
      }
    }

    i.bi + span:not(:empty) {
      margin-left: 10px;
    }

    &.is-icon-only i.bi {
      margin: -6px;
      &.large {
        margin: -8px;
      }
    }
  }
}

</style>
