// Styles
import './VTooltip.sass'

// Components
import { VOverlay } from '@/components/VOverlay'
import { makeVOverlayProps } from '@/components/VOverlay/VOverlay'

// Composables
import { useColor } from '@/composables/color'
import { forwardRefs } from '@/composables/forwardRefs'
import { useProxiedModel } from '@/composables/proxiedModel'
import { useScopeId } from '@/composables/scopeId'

// Utilities
import { computed, mergeProps, ref, toRef, useId } from 'vue'
import { genericComponent, omit, propsFactory, useRender } from '@/util'

// Types
import type { StrategyProps } from '@/components/VOverlay/locationStrategies'
import type { OverlaySlots } from '@/components/VOverlay/VOverlay'

export const makeVTooltipProps = propsFactory({
  id: String,
  interactive: Boolean,
  text: String,
  color: String,

  ...omit(makeVOverlayProps({
    closeOnBack: false,
    location: 'end' as const,
    locationStrategy: 'connected' as const,
    eager: true,
    minWidth: 0,
    offset: 10,
    openOnClick: false,
    openOnHover: true,
    origin: 'auto' as const,
    scrim: false,
    scrollStrategy: 'reposition' as const,
    transition: null,
  }), [
    'absolute',
    'retainFocus',
    'captureFocus',
    'disableInitialFocus',
  ]),
}, 'VTooltip')

export const VTooltip = genericComponent<OverlaySlots>()({
  name: 'VTooltip',

  props: makeVTooltipProps(),

  emits: {
    'update:modelValue': (value: boolean) => true,
  },

  setup (props, { slots }) {
    const isActive = useProxiedModel(props, 'modelValue')
    const { scopeId } = useScopeId()

    const { colorClasses, colorStyles } = useColor(() => ({
      background: props.color,
    }))

    const uid = useId()
    const id = toRef(() => props.id || `v-tooltip-${uid}`)

    const overlay = ref<VOverlay>()

    const location = computed(() => {
      return props.location.split(' ').length > 1
        ? props.location
        : props.location + ' center' as StrategyProps['location']
    })

    const origin = computed(() => {
      return (
        props.origin === 'auto' ||
        props.origin === 'overlap' ||
        props.origin.split(' ').length > 1 ||
        props.location.split(' ').length > 1
      ) ? props.origin
        : props.origin + ' center' as StrategyProps['origin']
    })

    const transition = toRef(() => {
      if (props.transition != null) return props.transition
      return isActive.value ? 'scale-transition' : 'fade-transition'
    })

    const activatorProps = computed(() =>
      mergeProps({
        'aria-describedby': id.value,
      }, props.activatorProps)
    )

    useRender(() => {
      const overlayProps = VOverlay.filterProps(props)

      return (
        <VOverlay
          ref={ overlay }
          class={[
            'v-tooltip',
            { 'v-tooltip--interactive': props.interactive },
            props.class,
          ]}
          style={[
            props.style,
          ]}
          id={ id.value }
          { ...overlayProps }
          contentClass={[
            colorClasses.value,
            props.contentClass,
          ]}
          contentProps={ mergeProps(
            { style: [colorStyles.value] },
            props.contentProps,
          )}
          v-model={ isActive.value }
          transition={ transition.value }
          absolute
          location={ location.value }
          origin={ origin.value }
          role="tooltip"
          activatorProps={ activatorProps.value }
          _disableGlobalStack
          { ...scopeId }
        >
          {{
            activator: slots.activator,
            default: (...args) => slots.default?.(...args) ?? props.text,
          }}
        </VOverlay>
      )
    })

    return forwardRefs({}, overlay)
  },
})

export type VTooltip = InstanceType<typeof VTooltip>
