/**
 * 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 type {
  ITabsState,
  ITabsApi,
  ITabsProps,
  ISharedRenderlessParamHooks,
  ITabsRenderlessParamUtils,
  ITabsRenderlessParams
} from '@/types'
import {
  calcMorePanes,
  calcExpandPanes,
  calcPaneInstances,
  handleTabClick,
  handleTabAdd,
  handleTabRemove,
  setCurrentName,
  changeCurrentName,
  created,
  changeDirection,
  handleTabDragStart,
  handleTabDragOver,
  handleTabDragEnd
} from './index'

export const api = [
  'state',
  'handleTabAdd',
  'calcPaneInstances',
  'handleTabRemove',
  'handleTabClick',
  'handleTabDragStart',
  'handleTabDragOver',
  'handleTabDragEnd',
  'setCurrentName',
  'getNavRefs'
]

const initState = ({ reactive, props }: Pick<ITabsRenderlessParams, 'reactive' | 'props'>): ITabsState =>
  reactive({
    panes: [],
    currentName: props.modelValue || props.activeName,
    currentIndex: -1,
    showPanesCount: -1,
    startX: 0,
    startY: 0,
    deltaX: 0,
    deltaY: 0,
    offsetX: 0,
    offsetY: 0,
    direction: '',
    expandPanesWidth: '',
    activeIndex: 1,
    separator: props.separator,
    headerOnly: props.headerOnly
  }) as ITabsState

const initWatcher = ({
  watch,
  props,
  api,
  state,
  nextTick,
  refs
}: Pick<ITabsRenderlessParams, 'watch' | 'props' | 'api' | 'state' | 'nextTick' | 'refs'>) => {
  watch(() => props.modelValue, api.setCurrentName)

  watch(() => props.activeName, api.setCurrentName)

  watch(
    () => state.currentName,
    () => {
      nextTick(() => {
        refs.nav.scrollToActiveTab()
      })
    },
    { deep: true }
  )

  watch(
    () => props.showMoreTabs,
    (value) => {
      if (!value) {
        state.morePanes = []
        state.showPanesCount = -1
      }
    },
    { immediate: true }
  )
}

export const renderless = (
  props: ITabsProps,
  { onMounted, onUpdated, provide, reactive, watch, onUnmounted }: ISharedRenderlessParamHooks,
  { vm, refs, parent, emit, constants, nextTick, childrenHandler }: ITabsRenderlessParamUtils
): ITabsApi => {
  const api = {} as ITabsApi
  const state: ITabsState = initState({ reactive, props })

  Object.assign(api, {
    state,
    handleTabAdd: handleTabAdd(emit),
    handleTabRemove: handleTabRemove({ emit, props }),
    changeDirection: changeDirection({ props, state }),
    changeCurrentName: changeCurrentName({ emit, state }),
    calcMorePanes: calcMorePanes({ parent, props, state, refs }),
    calcExpandPanes: calcExpandPanes({ parent, props, state }),
    calcPaneInstances: calcPaneInstances({ constants, parent, state, childrenHandler }),
    handleTabDragStart: handleTabDragStart({ emit }),
    handleTabDragOver: handleTabDragOver({ emit }),
    handleTabDragEnd: handleTabDragEnd({ state, emit }),
    handleTabClick: handleTabClick({ api, emit, props, refs }),
    setCurrentName: setCurrentName({ api, props, refs, state }),
    created: created({ api, parent, state })
  })

  api.created()

  provide('rootTabs', parent)

  provide('separator', state.separator)

  initWatcher({ watch, props, api, state, nextTick, refs })

  onMounted(() => {
    api.calcPaneInstances()
    api.calcMorePanes()
    api.calcExpandPanes()
  })

  onUpdated(() => {
    api.calcPaneInstances()
    api.calcMorePanes()
    api.calcExpandPanes()
  })

  onUnmounted(() => {
    vm.$off('tab-nav-update')
  })

  return api
}