/**
 * Copyright (c) 2022 - present TinyVue Authors.
 * Copyright (c) 2022 - present Huawei Cloud Computing Technologies Co., Ltd.
 *
 * Use of this source code is governed by an MIT-style license.
 *
 * THE OPEN SOURCE SOFTWARE IN THIS PRODUCT IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL,
 * BUT WITHOUT ANY WARRANTY, WITHOUT EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR
 * A PARTICULAR PURPOSE. SEE THE APPLICABLE LICENSES FOR MORE DETAILS.
 *
 */

import { on, off } from '@opentiny/utils'
import { touchStart, touchMove } from '@opentiny/utils'
import { getScroller } from '../dropdown-menu'
import { isNull } from '@opentiny/utils'

export const getStyle = (props) => () => {
  const style = { ...props.popupStyle }

  if (!isNull(props.duration)) {
    const key = props.position === 'center' ? 'animationDuration' : 'transitionDuration'

    style[key] = `${props.duration}s`
  }

  return style
}

export const watchValue = (api) => (value) => {
  const type = value ? 'open' : 'close'
  api[type]()
}

export const open =
  ({ api, constants, emit, props, state }) =>
  () => {
    if (state.opened) {
      return
    }

    if (props.zIndex !== undefined) {
      state.context.zIndex = props.zIndex
    }

    api.renderOverlay()

    state.opened = true

    emit('open')

    if (props.lockScroll) {
      on(document, 'touchstart', touchStart)
      on(document, 'touchmove', api.onTouchMove)

      if (!state.context.lockCount) {
        document.body.classList.add(constants.OVERFLOWHIDDEN)
      }

      state.context.lockCount++
    }
  }

export const close =
  ({ api, constants, emit, props, state }) =>
  () => {
    if (!state.opened) {
      return
    }

    if (props.lockScroll) {
      state.context.lockCount--

      off(document, 'touchstart', touchStart)
      off(document, 'touchmove', api.onTouchMove)

      if (!state.context.lockCount) {
        document.body.classList.remove(constants.OVERFLOWHIDDEN)
      }
    }

    state.opened = false

    emit('update:modelValue', false)
    emit('close')
  }

export const onTouchMove =
  ({ vm, state }) =>
  (event) => {
    touchMove(event)

    const direction = state.deltaY > 0 ? '10' : '01'
    const el = getScroller()(event.target, vm.$refs.$el)
    const { scrollHeight, offsetHeight, scrollTop } = el
    let status = '11'

    if (scrollTop === 0) {
      status = offsetHeight >= scrollHeight ? '00' : '01'
    } else if (scrollTop + offsetHeight >= scrollHeight) {
      status = '10'
    }

    if (status !== '11' && state.direction === 'vertical' && !(parseInt(status, 2) & parseInt(direction, 2))) {
      event.preventDefault()
    }
  }

export const renderOverlay =
  ({ api, nextTick, props, state }) =>
  () => {
    if (!props.modelValue) {
      return
    }

    nextTick(() => {
      api.updateZIndex(props.overlay ? 1 : 0)

      if (props.overlay) {
        state.zIndex = state.context.zIndex++
      }
    })
  }

export const updateZIndex =
  ({ vm, state }) =>
  (value = 0) =>
    (vm.$refs.popup.style.zIndex = ++state.context.zIndex + value)

export const clickOverlay =
  ({ api, props, emit }) =>
  () => {
    if (props.closeOnClickOverlay) {
      api.close()
      emit('click-overlay')
    }
  }

export const closed = (emit) => () => emit('closed')

export const opened = (emit) => () => emit('opened')
