// Utilities
import { computed, inject, provide, shallowRef, useId } from 'vue'

// Types
import type { InjectionKey, MaybeRefOrGetter, Ref } from 'vue'

// Depth
export const DepthKey: InjectionKey<Ref<number>> = Symbol.for('vuetify:depth')

export function useDepth (hasPrepend?: Ref<boolean>) {
  const parent = inject(DepthKey, shallowRef(-1))

  const depth = computed(() => parent.value + 1 + (hasPrepend?.value ? 1 : 0))

  provide(DepthKey, depth)

  return depth
}

// List
export const ListKey: InjectionKey<{
  filterable: MaybeRefOrGetter<boolean>
  hasPrepend: Ref<boolean>
  updateHasPrepend: (value: boolean) => void
  trackingIndex: Ref<number>
  navigationStrategy: Ref<'focus' | 'track'>
  uid: string
}> = Symbol.for('vuetify:list')

type InjectedListOptions = {
  filterable: MaybeRefOrGetter<boolean>
  trackingIndex?: Ref<number>
  navigationStrategy?: Ref<'focus' | 'track'>
  uid?: string
}

export function createList (options: InjectedListOptions = { filterable: false }) {
  const parent = inject(ListKey, {
    filterable: false,
    hasPrepend: shallowRef(false),
    updateHasPrepend: () => null,
    trackingIndex: shallowRef(-1),
    navigationStrategy: shallowRef('focus' as 'focus' | 'track'),
    uid: '',
  })

  const {
    filterable,
    trackingIndex = parent.trackingIndex,
    navigationStrategy = parent.navigationStrategy,
    uid = parent.uid || useId(),
  } = options

  const data = {
    filterable: parent.filterable || filterable,
    hasPrepend: shallowRef(false),
    updateHasPrepend: (value: boolean) => {
      if (value) data.hasPrepend.value = value
    },
    trackingIndex,
    navigationStrategy,
    uid,
  }

  provide(ListKey, data)

  return parent
}

export function useList () {
  return inject(ListKey, null)
}
