import { wrapInList, liftListItem } from 'prosemirror-schema-list'
import type { Node, NodeType } from 'prosemirror-model'
import type { Transaction, EditorState } from 'prosemirror-state'
import { findParentNode, isList } from '../utils'

interface Attr {
  [key: string]: number | string
}

interface TextStyleAttr {
  color?: string
  fontsize?: string
}

export const toggleList = (listType: NodeType, itemType: NodeType, listStyleType: string, textStyleAttr: TextStyleAttr = {}) => {
  return (state: EditorState, dispatch: (tr: Transaction) => void) => {
    const { schema, selection } = state
    const { $from, $to } = selection
    const range = $from.blockRange($to)

    if (!range) return false

    const parentList = findParentNode((node: Node) => isList(node, schema))(selection)

    if (range.depth >= 1 && parentList && range.depth - parentList.depth <= 1) {
      if (parentList.node.type === listType && !listStyleType) {
        return liftListItem(itemType)(state, dispatch)
      }

      if (isList(parentList.node, schema) && listType.validContent(parentList.node.content)) {
        const { tr } = state

        const nodeAttrs: Attr = {
          ...parentList.node.attrs,
          ...textStyleAttr,
        }
        if (listStyleType) nodeAttrs.listStyleType = listStyleType

        tr.setNodeMarkup(parentList.pos, listType, nodeAttrs)

        if (dispatch) dispatch(tr)

        return false
      }
    }

    const nodeAttrs: Attr = {
      ...textStyleAttr,
    }
    if (listStyleType) nodeAttrs.listStyleType = listStyleType

    return wrapInList(listType, nodeAttrs)(state, dispatch)
  }
}