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

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

const DEBOUNCE_TIME = 800
const MAX_HISTORY_LENGTH = 20

export const useHistory = () => {
  const project = ref<IProject>()
  const projectRevision = ref(0)
  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 projectHistory = useDebouncedRefHistory(project, {
    capacity: MAX_HISTORY_LENGTH,
    clone: klona,
    debounce: DEBOUNCE_TIME,
    deep: true,
    flush: 'post',
    shouldCommit: () => {
      operationHistory.commit()
      projectRevision.value += 1
      return true
    }
  })

  const {
    history,
    undo: _undo,
    redo: _redo,
    canRedo,
    canUndo,
    clear
  } = projectHistory

  let pauseDepth = 0

  const pauseHistory = () => {
    if (pauseDepth === 0) {
      projectHistory.pause()
    }
    pauseDepth = 1
  }

  const resumeHistory = (commit = true) => {
    if (pauseDepth === 0) return

    pauseDepth = 0
    projectHistory.resume(commit)
  }

  const undo = () => {
    _undo()
    operationHistory.undo()
    projectRevision.value += 1
  }
  const redo = () => {
    _redo()
    operationHistory.redo()
    projectRevision.value += 1
  }

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

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

    initHistory,
    project,
    projectRevision,
    activePageId,
    openPageIds,
    activeWidgets
  }
}
