export const computedRootStyle =
  ({ props, state }) =>
  () => {
    return {
      height: state.isFixed ? `${state.rootHeight}px` : '',
      width: state.isFixed ? `${state.rootWidth}px` : ''
    }
  }

export const computedStickyStyle =
  ({ props, state }) =>
  () => {
    if (!state.isFixed) return {}

    const offset = props.offset ? (typeof props.offset === 'number' ? props.offset + 'px' : props.offset) : 0

    return {
      height: `${state.rootHeight}px`,
      width: `${state.rootWidth}px`,
      top: props.position === 'top' ? offset : '',
      bottom: props.position === 'bottom' ? offset : '',
      transform: state.transform ? `translateY(${state.transform}px)` : '',
      zIndex: props.zIndex
    }
  }

export const updateRoot =
  ({ props, state, emit, api }) =>
  () => {
    if (!state.scrollParent || !state.target) return

    api.getRootRect()

    state.scrollTop =
      state.scrollParent instanceof Window ? document.documentElement.scrollTop : state.scrollParent.scrollTop || 0

    if (props.target) {
      state.targetRect = api.useRect(state.target)
    }

    if (props.position === 'top') {
      if (props.target) {
        const difference = state.targetRect.bottom - state.offset - state.rootHeight
        state.isFixed = state.offset > state.rootTop && state.targetRect.bottom > 0
        state.transform = difference < 0 ? difference : 0
      } else {
        state.isFixed = state.offset > state.rootTop
      }
    } else if (props.target) {
      const difference = state.windowHeight - state.targetRect.top - state.offset - state.rootHeight
      state.isFixed = state.windowHeight - state.offset < state.rootBottom && state.windowHeight > state.targetRect.top
      state.transform = difference < 0 ? -difference : 0
    } else {
      state.isFixed = state.windowHeight - state.offset < state.rootBottom
    }
    emit('scroll', { scrollTop: state.scrollTop, isFixed: state.isFixed })
  }

export const getRootRect =
  ({ state, vm, api }) =>
  () => {
    const rootRect = api.useRect(vm.$refs.root)

    state.rootHeight = rootRect.height
    state.rootWidth = rootRect.width
    state.rootTop = rootRect.top
    state.rootBottom = rootRect.bottom
  }

export const getTarget =
  ({ state, props, api }) =>
  () => {
    if (props.target) {
      state.target = document.querySelector<HTMLElement>(props.target) ?? undefined
      if (state.target) {
        state.targetRect = api.useRect(state.target)
      } else {
        throw new Error(`[AUI Error][aui-sticky] Target does not exist: ${props.target}`)
      }
    } else {
      state.target = document.documentElement
    }
  }

export const unitToPx = () => (value) => {
  if (typeof value === 'number') {
    return value
  }

  if (value.endsWith('rem')) {
    const rootFontSize = parseFloat(window.getComputedStyle(document.documentElement).fontSize)
    return parseFloat(value) * rootFontSize
  }

  if (value.endsWith('vh')) {
    return (parseFloat(value) / 100) * window.innerHeight
  }

  if (value.endsWith('vw')) {
    return (parseFloat(value) / 100) * window.innerWidth
  }

  return parseFloat(value)
}