/**
 * Usage:
 *
 * <errored-host></errored-host>
 */
if (typeof HTMLElement !== 'undefined') {
  class ErroredHost extends HTMLElement {
    get _root() {
      return this.shadowRoot || this;
    }

    constructor() {
      super();

      this.state = {};
      if (!this.props) {
        this.props = {};
      }

      this.componentProps = ['children', 'error'];

      // used to keep track of all nodes created by show/for
      this.nodesToDestroy = [];
      // batch updates
      this.pendingUpdate = false;

      this.attachShadow({ mode: 'open' });
    }

    destroyAnyNodes() {
      // destroy current view template refs before rendering again
      this.nodesToDestroy.forEach((el) => el.remove());
      this.nodesToDestroy = [];
    }

    connectedCallback() {
      this.getAttributeNames().forEach((attr) => {
        const jsVar = attr.replace(/-/g, '');
        const regexp = new RegExp(jsVar, 'i');
        this.componentProps.forEach((prop) => {
          if (regexp.test(prop)) {
            const attrValue = this.getAttribute(attr);
            if (this.props[prop] !== attrValue) {
              this.props[prop] = attrValue;
            }
          }
        });
      });

      this._root.innerHTML = `

        <template data-el="show-errored-host">
        <div class="error">
          <template data-el="div-errored-host-2">
            <!-- String(props.error) -->
          </template>
        </div>
        </template>

        <div class="arrow">👇 Uncaught error happened here 👇
          <span class="dev-tools">DevTools: Cmd+Alt+I</span>
        </div>
        <div class="div">
          <slot></slot>
        </div>

        <style>
          .error {
            border-radius: 5px 5px 0px 0;
            background: black;
            color: white;
            font-family: monospace;
            font-size: 12px;
            margin: 0;
            padding: 10px;
          }
          .arrow {
            background: #f47e81;
            color: black;
            font-size: 14px;
            padding: 10px;
            text-align: center;
            font-family: sans-serif;
          }
          .dev-tools {
            background: red;
            padding: 2px 5px;
            border-radius: 3px;
            font-weight: 800;
          }
          .div {
            outline: 5px solid red;
            border-radius: 10px;
          }
        </style>`;
      this.pendingUpdate = true;

      this.render();
      this.onMount();
      this.pendingUpdate = false;
      this.update();
    }

    showContent(el) {
      // https://developer.mozilla.org/en-US/docs/Web/API/HTMLTemplateElement/content
      // grabs the content of a node that is between <template> tags
      // iterates through child nodes to register all content including text elements
      // attaches the content after the template

      const elementFragment = el.content.cloneNode(true);
      const children = Array.from(elementFragment.childNodes);
      children.forEach((child) => {
        if (el?.scope) {
          child.scope = el.scope;
        }
        if (el?.context) {
          child.context = el.context;
        }
        this.nodesToDestroy.push(child);
      });
      el.after(elementFragment);
    }

    onMount() {}

    onUpdate() {}

    update() {
      if (this.pendingUpdate === true) {
        return;
      }
      this.pendingUpdate = true;
      this.render();
      this.onUpdate();
      this.pendingUpdate = false;
    }

    render() {
      // re-rendering needs to ensure that all nodes generated by for/show are refreshed
      this.destroyAnyNodes();
      this.updateBindings();
    }

    updateBindings() {
      this._root.querySelectorAll("[data-el='show-errored-host']").forEach((el) => {
        const whenCondition = this.props.error;
        if (whenCondition) {
          this.showContent(el);
        }
      });

      this._root.querySelectorAll("[data-el='div-errored-host-2']").forEach((el) => {
        this.renderTextNode(el, String(this.props.error));
      });
    }

    // Helper to render content
    renderTextNode(el, text) {
      const textNode = document.createTextNode(text);
      if (el?.scope) {
        textNode.scope = el.scope;
      }
      if (el?.context) {
        textNode.context = el.context;
      }
      el.after(textNode);
      this.nodesToDestroy.push(el.nextSibling);
    }
  }

  customElements.define('errored-host', ErroredHost);

  document.addEventListener('qerror', (ev) => {
    const ErrorOverlay = customElements.get('vite-error-overlay');
    if (!ErrorOverlay) {
      return;
    }
    const err = ev.detail.error;
    const overlay = new ErrorOverlay(err);
    document.body.appendChild(overlay);
  });
}
