/**
 * Utility functions for EdGEL components.
 */

/* global global */

function baseStore() {
  if (typeof window === 'undefined') {
    global.window = {
      document: {}
    }
  }

  if (!window.EdGEL) {
    window.EdGEL = {}
  }

  if (!window.EdGEL.backlog) {
    window.EdGEL.backlog = []
  }

  return window.EdGEL
}

export function getId(base) {
  const EdGEL = baseStore()

  if (!EdGEL.idCounter) {
    EdGEL.idCounter = 0
  }

  if (!base) {
    base = 'edgel'
  }

  return `${base}-${EdGEL.idCounter++}`
}

function clearBacklog() {
  const EdGEL = baseStore()

  if (EdGEL.stylesheet) {
    while (EdGEL.backlog.length) {
      const ce = EdGEL.backlog.shift()
      window.customElements.define(...ce)
    }
  }
}

// Find the EdGEL CSS loaded to the page and construct a new stylesheet based on it since
// only constructed stylesheets can be adopted in our components.
function findEdgelCss() {
  const EdGEL = baseStore()
  if (!EdGEL.stylesheet) {
    for (const sheet of window.document.styleSheets) {
      const found = Object.keys(sheet.cssRules).some(k => sheet.cssRules[k].cssText.includes('--edgel-body-bg:'))

      if (found) {
        EdGEL.stylesheet = new CSSStyleSheet()
        let cssText = ''
        for (const rule of sheet.cssRules) {
          cssText += rule.cssText
        }

        EdGEL.stylesheet.replaceSync(cssText)
      }
    }
  }

  clearBacklog()
}

// If we haven't found any EdGEL CSS loaded on the page, add a <style> tag to the page to do that.
function loadCSS() {
  const EdGEL = baseStore()

  if (EdGEL.stylesheet === undefined) {
    const brand = document.querySelector('html').dataset.edgelBrand || 'blue-university'

    // Add style for hiding FOUC since there will be a delay while the EdGEL stylesheet is loaded
    const sheet = new CSSStyleSheet()
    sheet.replaceSync(':not(:defined) { display: none; }')
    document.adoptedStyleSheets = [...document.adoptedStyleSheets, sheet]

    const linkElement = document.createElement('link')
    linkElement.setAttribute('rel', 'stylesheet')
    linkElement.setAttribute('type', 'text/css')
    linkElement.setAttribute('href', `../../dist/css/edgel-${brand}.min.css`)
    linkElement.addEventListener('load', findEdgelCss, { once: true })
    document.querySelector('head').append(linkElement)

    // Avoid re-entry adding a second link tag
    EdGEL.stylesheet = null
  }
}

export function edgelCSS() {
  const EdGEL = baseStore()
  return EdGEL.stylesheet
}

// Pause defining a custom element until EdGEL CSS has been loaded to the page
// since all elements adopt the same constructed stylesheet.
export function customElement(tag, Element) {
  if (typeof window !== 'undefined' && !window.customElements.get(tag)) {
    const EdGEL = baseStore()
    let missingCSS = false

    if (!EdGEL.stylesheet) {
      findEdgelCss()

      if (!EdGEL.stylesheet) {
        missingCSS = true
      }
    }

    if (missingCSS) {
      EdGEL.backlog.push([tag, Element])
      loadCSS()
    } else {
      window.customElements.define(tag, Element)
    }
  }
}
