import { globalConfig } from '../private.config/instance-config.js'

const nodesList = []
const portalTypeList = []

let portalIndex = 1
let target = __QUASAR_SSR_SERVER__ ? void 0 : document.body

export function createGlobalNode(id, portalType, parentEl) {
  const el = document.createElement('div')

  el.id =
    portalType !== void 0 ? `q-portal--${portalType}--${portalIndex++}` : id

  if (globalConfig.globalNodes !== void 0) {
    const cls = globalConfig.globalNodes.class
    if (cls !== void 0) {
      el.className = cls
    }
  }

  ;(parentEl || target).append(el)
  nodesList.push(el)
  portalTypeList.push(portalType)

  return el
}

export function removeGlobalNode(el) {
  const nodeIndex = nodesList.indexOf(el)

  if (nodeIndex !== -1) {
    nodesList.splice(nodeIndex, 1)
    portalTypeList.splice(nodeIndex, 1)
  }

  el.remove()
}

/**
 * Re-appends the global nodes living directly under the current target, in
 * their creation order. Portals paint above a same-z-index sibling only while
 * they come later in the DOM, which holds naturally until something else gets
 * appended to <body> after them -- the fullscreen mixin does exactly that
 * with the element it detaches, burying every already-open popup (#18513).
 */
export function bringGlobalNodesToFront() {
  const activeEl = document.activeElement

  nodesList.forEach(node => {
    if (node.parentElement === target) {
      target.append(node)
    }
  })

  // moving a node drops the focus it holds; restore it
  if (
    activeEl !== null &&
    activeEl !== document.activeElement &&
    activeEl.isConnected
  ) {
    activeEl.focus({ preventScroll: true })
  }
}

export function changeGlobalNodesTarget(newTarget) {
  if (newTarget === target) return

  target = newTarget

  if (
    target === document.body ||
    // or we have less than 2 dialogs:
    portalTypeList.reduce(
      (acc, type) => (type === 'dialog' ? acc + 1 : acc),
      0
    ) < 2
  ) {
    nodesList.forEach(node => {
      if (!node.contains(target)) {
        target.append(node)
      }
    })

    return
  }

  const lastDialogIndex = portalTypeList.lastIndexOf('dialog')

  for (let i = 0; i < nodesList.length; i++) {
    const el = nodesList[i]

    if (
      (i === lastDialogIndex || portalTypeList[i] !== 'dialog') &&
      !el.contains(target)
    ) {
      target.append(el)
    }
  }
}
