/**
 * 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 { formatDateByPattern as format } from '@opentiny/utils'
import type {
  ITimelineItemRenderlessParams,
  ITimelineItem,
  ITimelineStatusCls,
  ITimelineCustomCls,
  ITimelineItemApi
} from '@/types'

export const getDate = (dateTime: string): { date: string; time: string } => ({
  date: format(dateTime, 'yyyy-MM-dd'),
  time: format(dateTime, 'hh:mm')
})

export const getStatus =
  ({ state, t }: Pick<ITimelineItemRenderlessParams, 'state' | 't'>) =>
  (value: number): string => {
    const status = state.current - value

    return status > 0 ? t('ui.steps.done') : status === 0 ? t('ui.steps.doing') : t('ui.steps.wait')
  }

export const computedWidth =
  () =>
  (width: string | number): string | number => {
    return /^\d+$/.test(String(width)) ? `${width}px` : width || ''
  }

export const handleClick =
  ({ emit, state, props }: Pick<ITimelineItemRenderlessParams, 'emit' | 'state' | 'props'>) =>
  (node: ITimelineItem): void => {
    const index = props.nodeIndex
    if (!node.disabled) {
      emit('click', state.isReverse ? state.nodesLength - index - 1 : index, node)
    }
  }

export const getStatusCls =
  ({ constants, state, props }: Pick<ITimelineItemRenderlessParams, 'constants' | 'state' | 'props'>) =>
  (node: ITimelineItem): ITimelineStatusCls => {
    const index = props.nodeIndex

    const { PROCESS_DONE_CLS, PROCESS_CUR_CLS, PROCESS_WAIT_CLS, PROCESS_DISABLED_CLS, PROCESS_ERROR_CLS } = constants
    const cls = {}
    const reverse = state.isReverse

    if (node?.disabled) {
      cls[PROCESS_DISABLED_CLS] = true
    } else if (node?.error) {
      cls[PROCESS_ERROR_CLS] = true
    } else {
      cls[PROCESS_DONE_CLS] = reverse ? index > state.current : index < state.current
      cls[PROCESS_CUR_CLS] = index === state.current
      cls[PROCESS_WAIT_CLS] = reverse ? index < state.current : index > state.current
    }

    return cls
  }

export const computedCurrent =
  ({ state, api }: Pick<ITimelineItemRenderlessParams, 'state' | 'api'>) =>
  (): number =>
    state.isReverse ? state.nodesLength - api.rootProps.active - 1 : api.rootProps.active

export const computedIsReverse = (api: ITimelineItemApi) => (): boolean =>
  api.rootProps.reverse && api.rootProps.vertical

export const computedItemCls =
  ({ props, api, state }: Pick<ITimelineItemRenderlessParams, 'props' | 'api' | 'state'>) =>
  (): ITimelineCustomCls => {
    const itemClass: ITimelineCustomCls = []
    if (api.rootProps.vertical) {
      itemClass.push('timeline')
      if (props.node.type) {
        itemClass.push(`timeline-item--${props.node.type}`)
      }
    } else {
      itemClass.push('normal')
    }

    if (!props.node.type) {
      itemClass.push(api.getStatusCls(props.node))
    }

    if (state.computedLineWidth) {
      itemClass.push('no-flex')
    }

    return itemClass
  }

export const computedIconClass =
  ({ props, api }: Pick<ITimelineItemRenderlessParams, 'props' | 'api'>) =>
  (): Array<string | Object> => {
    let iconClass = ['icon', { 'step-icon': api.rootProps.textPosition === 'right' }]
    const defaultIcons = ['success', 'warning', 'error']

    if (defaultIcons.includes(props.node[props.autoColorField])) {
      iconClass.push(`icon-${props.node[props.autoColorField]}`)
    } else if (props.node[props.autoColorField]) {
      iconClass.push('icon-custom')
    }

    return iconClass
  }

export const computedItemStyle =
  ({ props, state, api }: Pick<ITimelineItemRenderlessParams, 'props' | 'state' | 'api'>) =>
  (): { width?: string | number; height?: string | number; flex?: string } | null => {
    const index = props.nodeIndex
    const { computedSpace, nodesLength } = state
    const { textPosition, vertical } = api.rootProps

    if (vertical) {
      return { height: index === nodesLength - 1 ? '' : computedSpace }
    }

    if (textPosition === 'right') {
      if (computedSpace && !state.computedLineWidth) {
        return { flex: `0 0 ${computedSpace}` }
      }

      return null
    }

    return { width: computedSpace || 100 / nodesLength + '%' }
  }