// @ts-nocheck
// 扩展 ant-design 的组件
import Vue from 'vue'
import merge from 'lodash/merge'
import moment from 'moment'
import { FormModel, Card, Tabs, LocaleProvider, Empty, Input, Modal } from 'ant-design-vue'
import CalendarMixin from 'ant-design-vue/es/vc-calendar/src/mixin/CalendarMixin'
import VcTable from 'ant-design-vue/es/vc-table/src/Table'
import FormItem from 'ant-design-vue/es/form-model/FormItem'
import draggableModal from './sd-draggable-modal'
// 导入自定义的图标
import './sd-icon-library'

const isIE = navigator.userAgent.includes('Trident/')

// 设置默认的表单校验错误消息
FormModel.props.validateMessages.default = () => {
  function getMessage(obj) {
    // 把包含 %s 的替换成函数，因为要去掉第一个字段名称
    const result = {}
    iterate(obj, result, (str) => {
      const parts = str.split(/%s/g)
      if (parts.length === 1) return str
      return (name, ...rest) => {
        return parts.map((part, index) => part + (rest[index] || '')).join('')
      }
    })
    return result
  }

  function iterate(obj, objTo, fn) {
    for (const property in obj) {
      if (typeof obj[property] === 'object') {
        objTo[property] = {}
        iterate(obj[property], objTo[property], fn)
      } else {
        objTo[property] = fn(obj[property])
      }
    }
  }

  // 完整的错误消息，见 https://github.com/yiminghe/async-validator/blob/master/src/messages.js
  return getMessage({
    default: '出现校验错误',
    required: '不能为空',
    enum: '必须是 %s 之一',
    whitespace: '不能为空',
    date: {
      format: '日期 %s 不符合 %s 格式',
      parse: '日期不能解析, %s 无效',
      invalid: '日期 %s 无效',
    },
    types: {
      string: '必须为字符串',
      method: '必须为函数',
      array: '必须为数组',
      object: '必须为对象',
      number: '必须为数字',
      date: '比如为日期',
      boolean: '必须为布尔值',
      integer: '必须为整数',
      float: '必须为浮点数',
      regexp: '不是合法的正则表达式',
      email: '不是合法的 email 地址',
      url: '不是合法的 URL',
      hex: '不是合法的十六进制数',
    },
    string: {
      len: '字符数必须等于 %s',
      min: '不能少于 %s 个字符',
      max: '不能超过 %s 个字符',
      range: '字符数必须在 %s 和 %s 之间',
    },
    number: {
      len: '必须等于 %s',
      min: '不能小于 %s',
      max: '不能大于 %s',
      range: '必须在 %s 和 %s 之间',
    },
    array: {
      len: '必须选择 %s 个',
      min: '最少选择 %s 个',
      max: '最多选择 %s 个',
      range: '必须选择 %s - %s 个',
    },
    pattern: {
      mismatch: '值 %s 与表达式 %s 不匹配',
    },
  })
}

// Card默认无边框
Card.props.bordered.default = false

// tab页默认的动画效果
Tabs.props.animated.default = () => ({ inkBar: true, tabPane: false })

// 避免对话框关闭后，语言恢复成英文
LocaleProvider.beforeDestroy = () => {}

// 空状态默认使用简洁版
Empty.props.image.default = () => Empty.PRESENTED_IMAGE_SIMPLE

if (isIE) {
  // 修复bug：https://github.com/vueComponent/ant-design-vue/issues/2592
  const handleReset = Input.methods.handleReset
  Input.methods.handleReset = function(e) {
    handleReset.call(this, { type: 'click' })
  }
  const handleResetTextArea = Input.TextArea.methods.handleReset
  Input.TextArea.methods.handleReset = function(e) {
    handleResetTextArea.call(this, { type: 'click' })
  }
}

// 避免切换tab页时，内部的节点被移动位置
const tabPaneRender = Tabs.TabPane.render
Tabs.TabPane.render = function(h) {
  const vNode = tabPaneRender.call(this, h)
  // 过滤掉 Sentinel子节点
  vNode.children = vNode.children.filter((child) => !child.tag?.endsWith('-Sentinel'))
  return vNode
}

// 先注册antd标准的Modal，再用我们的覆盖掉
Vue.use(Modal)
// eslint-disable-next-line vue/match-component-file-name
Vue.component('AModal', draggableModal)

// 修复ant design表格components属性没有响应式的问题
VcTable.mixins.push({
  watch: {
    components() {
      this.sComponents = merge(
        {
          table: 'table',
          header: {
            wrapper: 'thead',
            row: 'tr',
            cell: 'th',
          },
          body: {
            wrapper: 'tbody',
            row: 'tr',
            cell: 'td',
          },
        },
        this.components
      )
    },
  },
})

// 日期选择器不显示秒，但是选择出来的值包含秒。去掉多余的部分
const onSelect = CalendarMixin.methods.onSelect
CalendarMixin.methods.onSelect = function(value, cause) {
  // 排除掉周选择器等
  if (this.format.includes('YYYY')) {
    // 先把值格式化成字符串，再解析回去，这样就丢弃了不需要的部分
    const newValue = moment(value.format(this.format), this.format)
    return onSelect.call(this, newValue, cause)
  } else {
    return onSelect.call(this, value, cause)
  }
}

// 值是数组类，初始值是undefined，reset时会报错
const resetField = FormItem.methods.resetField
FormItem.methods.resetField = function() {
  if (Array.isArray(this.fieldValue) && this.initialValue === undefined) {
    this.initialValue = []
  }
  return resetField.call(this)
}
