import { FiberFinish, FiberHost, HTMLElementEx, Fiber, Ref, TAG } from './type'
import { updateElement } from './dom'
import { isFn } from './reconcile'
export const commit = (fiber?: FiberFinish) => {
if (!fiber) {
return
}
refer(fiber.ref, fiber.node)
commitSibling(fiber.child)
let { op, ref, cur } = fiber.action || {}
let parent = fiber?.parent?.node
let suspenseNodeComment = null
if (parent?.nodeType === 8) {
if (parent?.nodeValue === 'Suspense') {
suspenseNodeComment = parent
}
parent = parent.parentNode as any
}
if (op & TAG.INSERT || op & TAG.MOVE) {
let comment = null
if (fiber.isComp) {
//@ts-ignore
comment = fiber?.node?.firstChild
}
parent.insertBefore(cur?.node, suspenseNodeComment ?? ref?.node)
if (fiber.isComp) {
fiber.node = comment
}
}
if (op & TAG.UPDATE) {
const node = fiber.node
updateElement(
node,
(fiber.alternate as FiberHost)?.props || {},
(fiber as FiberHost).props
)
}
fiber.action = null
commitSibling(fiber.sibling)
}
function commitSibling(fiber?: FiberFinish) {
if (fiber?.memo) {
commitSibling(fiber.sibling)
} else {
commit(fiber)
}
}
const refer = (ref?: Ref, dom?: HTMLElementEx) => {
if (ref) isFn(ref) ? ref(dom) : (ref.current = dom)
}
const kidsRefer = (kids: Fiber[]) => {
kids?.forEach((kid) => {
kid.kids && kidsRefer(kid.kids)
refer(kid.ref, null)
})
}
export const removeElement = (fiber: Fiber, flag: boolean = true) => {
if (fiber.isComp) {
fiber.hooks && fiber.hooks.list.forEach((e) => e[2] && e[2]())
} else {
if (flag) {
(fiber.node?.parentNode as any)?.removeChild(fiber.node)
flag = false
}
kidsRefer(fiber.kids)
refer(fiber.ref, null)
}
fiber?.kids?.forEach(v => removeElement(v, flag))
}