import { defineComponent, h, ref, watch } from 'vue'
import { CButton } from '../button/CButton'
import { CSpinner } from '../spinner/CSpinner'

import type { ComponentProps } from '../../utils/ComponentProps'

interface CLoadingButtonProps extends ComponentProps<typeof CButton> {
  disabledOnLoading?: boolean
  loading?: boolean
  spinnerType?: 'border' | 'grow'
  timeout?: number
}

const CLoadingButton = defineComponent({
  name: 'CLoadingButton',
  props: {
    /**
     * Makes button disabled when loading.
     */
    disabledOnLoading: Boolean,
    /**
     * Loading state (set to true to start animation).
     */
    loading: {
      type: Boolean,
      default: false,
      required: false,
    },
    /**
     * Sets type of spinner.
     *
     * @values 'border', 'grow'
     * @default 'border'
     */
    spinnerType: {
      type: String,
      default: 'border',
      required: false,
      validator: (value: string) => {
        return ['border', 'grow'].includes(value)
      },
    },
    /**
     * Automatically starts loading animation and stops after a determined amount of milliseconds.
     */
    timeout: {
      type: Number,
      default: undefined,
      required: false,
    },
    ...CButton.props,
  },
  emits: [
    /**
     * Event called when the user clicks on a component.
     */
    'click',
  ],
  setup(props: CLoadingButtonProps, { emit, slots }) {
    const loading = ref(props.loading)

    watch(
      () => props.loading,
      () => {
        loading.value = props.loading
      },
    )

    const handleOnClick = () => {
      emit('click')
      if (props.timeout) {
        loading.value = true
        setTimeout(() => {
          loading.value = false
        }, props.timeout)
      }
    }

    return () =>
      h(
        CButton,
        {
          ...props,
          class: ['btn-loading', { ['is-loading']: loading.value }],
          ...(props.disabledOnLoading && loading.value && { disabled: true }),
          onClick: () => handleOnClick(),
        },
        {
          default: () => [
            h(CSpinner, { class: 'btn-loading-spinner', size: 'sm', variant: props.spinnerType }),
            slots.default && slots.default(),
          ],
        },
      )
  },
})

export { CLoadingButton }
