import extensionUtil from '@/common/services/extension-util'

const loadEventDefine = (files) => {
  return Promise.all(
    files
      .filter((f) => !f.fileName.endsWith('-handler.vue'))
      .map((f) => {
        return f.getModule().then((module) => {
          // 去掉扩展名
          const name = f.fileName.replace(/\.\w+$/, '')
          module.default.inject = {
            SdEventsManage: { default: () => {} },
          }
          // 添加默认prop
          const props = module.default.props || {}
          if (!props.dataSource) {
            Object.assign(props, {
              dataSource: {
                type: Object,
                default: () => {},
              },
            })
            module.default.props = props
          }
          return { id: name, module }
        })
      }) || []
  )
}

const promisesForVue = []
const loadEventHandlers = (files, prefix = '') => {
  return files.map((f) => {
    const name = prefix + f.fileName.replace(/\.\w+$/, '')
    const type = f.fileName.endsWith('.js') ? 'js' : 'vue'
    const module =
      type === 'js'
        ? f.getModule
        : () => {
            if (!promisesForVue[name]) {
              // 对于组件的处理，做一次就行了，所以把promise缓存下来
              promisesForVue[name] = f.getModule().then((module) => {
                // 外边多包一层div，避免modal销毁的时候，DOM结构就找不到了
                const render = module.default.render
                module.default.render = function(h, context) {
                  return h('div', [render.call(this, h, context)])
                }
                return module
              })
            }
            return promisesForVue[name]
          }
    return { id: name, module, type }
  })
}

const sortEventsDefine = (a, b) => {
  return (a.module.metaInfo?.order || Infinity) - (b.module.metaInfo?.order || Infinity)
}

const eventHandlers = {
  loadBackEnd: () => {
    // 加载预置事件、自定义事件
    return loadEventDefine(
      extensionUtil.parse(
        require.context(`./back-end`, false, /\.vue$/, 'lazy'),
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/back-end\/.*\.vue$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/back-end`,
          false,
          /\.vue$/,
          'lazy'
        )
      )
    ).then((events) => events.sort(sortEventsDefine))
  },
  // 加载前端事件定义
  loadFrontEnd: (associateData) => {
    let files
    if (associateData === 'single') {
      // 加载前端事件定义：单数据关联
      files = extensionUtil.parse(
        require.context(`./front-end/single-data`, false, /\.vue$/, 'lazy'),
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/front-end\/single-data\/.*\.vue$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/front-end/single-data`,
          false,
          /\.vue$/,
          'lazy'
        )
      )
    } else if (associateData === 'multiple') {
      // 加载前端事件定义：多数据关联
      files = extensionUtil.parse(
        require.context('./front-end', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/front-end\/multiple-data\/.*\.vue$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/front-end/multiple-data`,
          false,
          /\.vue$/,
          'lazy'
        )
      )
    } else if (associateData === 'none') {
      // 加载前端事件定义：无数据关联
      files = extensionUtil.parse(
        require.context('./front-end', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/front-end\/none-data\/.*\.vue$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/front-end/none-data`,
          false,
          /\.vue$/,
          'lazy'
        )
      )
    } else {
      // 要加载的前端事件定义未知
      return Promise.resolve([])
    }
    return loadEventDefine(files).then((events) => events.sort(sortEventsDefine))
  },
  // 加载前端事件处理器
  loadFrontEndHandlers: () => {
    // 关联数据：单个
    const filesSingle = extensionUtil.parse(
      require.context(`./front-end/single-data`, false, /-handler(\.js|\.vue)$/, 'lazy'),
      require.context(
        `@product`,
        true,
        /_application-manage\/event-handlers\/front-end\/single-data\/.*-handler(\.js|\.vue)$/,
        'lazy'
      ),
      require.context(
        `@custom/_application-manage/event-handlers/front-end/single-data`,
        false,
        /-handler(\.js|\.vue)$/,
        'lazy'
      )
    )
    // 关联数据：多个
    const filesMulti = extensionUtil.parse(
      require.context('./front-end', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
      require.context(
        `@product`,
        true,
        /_application-manage\/event-handlers\/front-end\/multiple-data\/.*-handler(\.js|\.vue)$/,
        'lazy'
      ),
      require.context(
        `@custom/_application-manage/event-handlers/front-end/multiple-data`,
        false,
        /-handler(\.js|\.vue)$/,
        'lazy'
      )
    )
    // 关联数据：无
    const filesNone = extensionUtil.parse(
      require.context('./front-end', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
      require.context(
        `@product`,
        true,
        /_application-manage\/event-handlers\/front-end\/none-data\/.*-handler(\.js|\.vue)$/,
        'lazy'
      ),
      require.context(
        `@custom/_application-manage/event-handlers/front-end/none-data`,
        false,
        /-handler(\.js|\.vue)$/,
        'lazy'
      )
    )
    return loadEventHandlers(filesSingle, 'single-').concat(
      loadEventHandlers(filesMulti, 'multiple-'),
      loadEventHandlers(filesNone, 'none-')
    )
  },
  childTable: {
    loadFrontEnd: (associateData) => {
      let files
      if (associateData === 'multiple') {
        // 加载前端事件定义：多数据关联
        files = extensionUtil.parse(
          require.context(`./front-end/child-table/multiple-data`, false, /\.vue$/, 'lazy'),
          require.context(
            `@product`,
            true,
            /_application-manage\/event-handlers\/front-end\/child-table\/multiple-data\/.*\.vue$/,
            'lazy'
          ),
          require.context(
            `@custom/_application-manage/event-handlers/front-end/child-table/multiple-data`,
            false,
            /\.vue$/,
            'lazy'
          )
        )
      } else if (associateData === 'none') {
        // 加载前端事件定义：无数据关联
        files = extensionUtil.parse(
          require.context('./front-end/child-table', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
          require.context(
            `@product`,
            true,
            /_application-manage\/event-handlers\/front-end\/child-table\/none-data\/.*\.vue$/,
            'lazy'
          ),
          require.context(
            `@custom/_application-manage/event-handlers/front-end/child-table/none-data`,
            false,
            /\.vue$/,
            'lazy'
          )
        )
      } else {
        // 要加载的前端事件定义未知
        return Promise.resolve([])
      }
      return loadEventDefine(files).then((events) => events.sort(sortEventsDefine))
    },
    loadFrontEndHandlers: () => {
      // 关联数据：多个
      const filesMulti = extensionUtil.parse(
        require.context(
          `./front-end/child-table/multiple-data`,
          false,
          /-handler(\.js|\.vue)$/,
          'lazy'
        ),
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/front-end\/child-table\/multiple-data\/.*-handler(\.js|\.vue)$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/front-end/child-table/multiple-data`,
          false,
          /-handler(\.js|\.vue)$/,
          'lazy'
        )
      )
      // 关联数据：无
      const filesNone = extensionUtil.parse(
        require.context('./front-end/child-table', false, /\.xxx$/, 'lazy'), // 无预置事件，因必须传此参数，先占位
        require.context(
          `@product`,
          true,
          /_application-manage\/event-handlers\/front-end\/child-table\/none-data\/.*-handler(\.js|\.vue)$/,
          'lazy'
        ),
        require.context(
          `@custom/_application-manage/event-handlers/front-end/child-table/none-data`,
          false,
          /-handler(\.js|\.vue)$/,
          'lazy'
        )
      )
      return loadEventHandlers(filesMulti, 'multiple-').concat(
        loadEventHandlers(filesNone, 'none-')
      )
    },
  },
}

export default eventHandlers
