export const close =
  ({ state, emit, vm }) =>
  () => {
    state.search.input = ''
    vm.$refs.actionSheet.close()
    emit('close', false)
  }

export const watchVisible =
  ({ emit, state, props, api }) =>
  (bool) => {
    const { multiple, modelValue, menus } = props

    if (bool) {
      if (!state.lazy) {
        state.search.options = menus
      }

      api.searchMethod()
      multiple && api.watchModelValue(modelValue)
    }

    emit('update:visible', bool)
    setTimeout(() => {
      state.toggle = bool
    }, 0)
  }

export const watchModelValue =
  ({ props, state, emit }) =>
  (value) => {
    const { multiple, menus, valueField, textField, textSplit } = props

    if (multiple) {
      const ids = menus.map((option) => option[valueField])
      state.checkList = (value || []).map((id) => {
        return ids.includes(id) ? menus[ids.indexOf(id)] : { [valueField]: id, [textField]: id }
      })
    }

    const textStr = multiple
      ? state.checkList.map((data) => data[textField])
      : menus.filter((data) => data[valueField] === value).map((data) => data[textField])

    emit('update:text', textStr.join(textSplit))
  }

export const includeOptionIndex = (props) => (list, option) => {
  const { valueField } = props
  let OptionIndex = -1

  list.some((data, i) => {
    const isEqual = data[valueField] === option[valueField]
    isEqual && (OptionIndex = i)

    return isEqual
  })

  return OptionIndex
}

export const confirm =
  ({ state, props, api, emit }) =>
  () => {
    const { search, checkIds } = state

    if (!search.show) {
      emit('confirm', state)
      emit('update:visible', false)
      props.multiple && emit('update:modelValue', checkIds)
    } else {
      api.searchBoxToggle(false)
    }
  }

export const searchMethod =
  ({ state, props }) =>
  () => {
    const { input, options } = state.search
    const { searchConfig, textField, valueField, topConfig } = props
    const topOptionIds = (topConfig.options || []).map((item) => item[valueField])
    let list

    if (searchConfig && searchConfig.searchMethod) {
      list = searchConfig.searchMethod({ input, options }) || []
    } else {
      list = options.filter((item) => item[textField].includes(input) && !topOptionIds.includes(item[valueField]))
    }

    if (typeof list.then === 'function') {
      list.then((data) => (state.search.filterOptions = data))
    } else {
      state.search.filterOptions = list
    }
  }

export const searchBoxToggle =
  ({ state, props, api }) =>
  (bool) => {
    const { menus } = props

    state.search.input = ''

    if (bool) {
      if (!state.lazy) {
        state.search.options = menus
      }
      api.searchMethod()
    } else {
      api.close()
    }
  }

export const allCheckHandler =
  ({ state, props }) =>
  () => {
    state.checkList = state.checkList.length === props.menus.length ? [] : props.menus.slice()
  }

export const searchSelectHandler =
  ({ state, emit, api, props }) =>
  (option) => {
    const { valueField, multiple, requiredSelectedList } = props

    if (multiple) {
      const index = api.includeOptionIndex(state.checkList, option)

      if (index > -1 && requiredSelectedList.includes(option[valueField])) {
        emit('search-click', option, false)
        return
      }

      index > -1 ? state.checkList.splice(index, 1) : state.checkList.push(option)
    } else {
      api.searchBoxToggle(false)
      emit('update:modelValue', option[valueField])
      emit('confirm', option[valueField], option)
    }

    emit('search-click', option, true)
  }

export const toggleCheckList =
  ({ state }) =>
  (value) => {
    if (!state.checkList.length) {
      return
    }

    state.selected.show = value

    if (value) {
      state.selected.options = state.checkList.slice()
    } else {
      state.checkList = state.selected.options.slice()
    }
  }

export const clean =
  ({ state, props }) =>
  () => {
    const { valueField, requiredSelectedList } = props

    state.selected.options = state.selected.options.filter((item) => requiredSelectedList.includes(item[valueField]))
  }

export const selectedOptionHandler =
  ({ state, api }) =>
  (option) => {
    const index = api.includeOptionIndex(state.selected.options, option)

    if (index > -1) {
      state.selected.options.splice(index, 1)
    }
  }

export const load =
  ({ state, props, api }) =>
  () => {
    const { infiniteScroll } = props
    const { search } = state

    if (!infiniteScroll.load || state.search.loading) {
      return
    }

    const list = infiniteScroll.load({ input: search.input, options: search.options })

    if (!list) {
      return
    }

    if (typeof list.then === 'function') {
      state.search.loading = true
      list.then((data) => {
        state.search.loading = false
        state.search.options = search.options.concat(data)
        api.searchMethod()
      })
    } else {
      state.search.options = search.options.concat(list)
      api.searchMethod()
    }
  }