import { ref, computed } from 'vue'
import { useDebouncedRefHistory, useManualRefHistory } from '@vueuse/core'
import { klona } from 'klona'
import { isEqual } from 'lodash'

import type { IProject } from '@/store/modules/project'
import type { BaseWidget } from '@/types/baseWidget'

const DEBOUNCE_TIME = 300
const MAX_HISTORY_LENGTH = 20

export const useHistory = () => {
  const project = ref<IProject>()
  const activePageId = ref<string>()
  const openPageIds = ref<string[]>([])
  const activeWidgets = ref<BaseWidget[]>([])

  const operationInfo = computed({
    get: () => ({
      activePageId: activePageId.value,
      openPageIds: openPageIds.value,
      activeWidgets: activeWidgets.value
    }),
    set: (value) => {
      activePageId.value = value.activePageId
      openPageIds.value = value.openPageIds
      activeWidgets.value = value.activeWidgets
    }
  })

  const operationHistory = useManualRefHistory(operationInfo, {
    clone: klona,
    capacity: MAX_HISTORY_LENGTH
  })

  // 历史记录
  const {
    history,
    undo: _undo,
    redo: _redo,
    canRedo,
    canUndo,
    clear,
    last
  } = useDebouncedRefHistory(project, {
    capacity: MAX_HISTORY_LENGTH,
    clone: klona,
    debounce: DEBOUNCE_TIME,
    deep: true,
    shouldCommit: (_, newValue) => {
      const should = !isEqual(newValue, last.value?.snapshot)
      if (should) {
        operationHistory.commit()
      }
      return should
    }
  })

  const undo = () => {
    _undo()
    operationHistory.undo()
  }
  const redo = () => {
    _redo()
    operationHistory.redo()
  }

  /**
   * 初始化历史记录
   */
  const initHistory = async () => {
    setTimeout(() => {
      clear()
      operationHistory.clear()
    }, DEBOUNCE_TIME + 100)
  }

  return {
    history,
    undo,
    redo,
    canRedo,
    canUndo,
    clear,

    initHistory,
    project,
    activePageId,
    openPageIds,
    activeWidgets
  }
}
