/*!
 * Copyright (c) 2024-present, Okta, Inc. and/or its affiliates. All rights reserved.
 * The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
 *
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *
 * See the License for the specific language governing permissions and limitations under the License.
 */

import { createReactRootElements } from "./createReactRootElements.js";
import { encapsulateShadowDomFromGlobalStyles } from "./encapsulateShadowDomFromGlobalStyles.js";
import version from "./odysseyWebComponentVersion.generated.js";
export const webComponentDataAttributeName = "data-odyssey-react-web-component";
export const versionedWebComponentName = `odyssey-react-web-component-${version}`.toLowerCase();
const SsrFriendlyHtmlElementClass = "HTMLElement" in globalThis ? HTMLElement : class {};
export class WebComponentClass extends SsrFriendlyHtmlElementClass {
  #getReactComponent = null;
  #reactRootElements;
  elementName = this.localName;
  reactRootPromise = Promise.resolve(null);
  constructor() {
    super();
    this.#reactRootElements = createReactRootElements();
    const {
      appRootElement,
      stylesRootElement
    } = this.#reactRootElements;
    const shadowRoot = this.attachShadow({
      mode: "open"
    });
    shadowRoot.appendChild(stylesRootElement);
    shadowRoot.appendChild(appRootElement);
  }
  setGetReactComponent(getReactComponent) {
    this.reactRootPromise = this.reactRootPromise.then(reactRoot => {
      this.#getReactComponent = getReactComponent;
      if (reactRoot) {
        reactRoot.render(this.#getReactComponent(this.#reactRootElements));
      } else {}
      return reactRoot;
    });
  }
  connectedCallback() {
    encapsulateShadowDomFromGlobalStyles({
      nonce: this.getAttribute("nonce") || window.cspNonce,
      stylesRootElement: this.#reactRootElements.stylesRootElement
    });
    this.reactRootPromise = this.reactRootPromise.then(reactRoot => {
      if (reactRoot) {
        throw new Error(`connectedCallback fired when reactRoot is already mounted.`);
      }
      return import("react-dom/client").then(({
        createRoot
      }) => createRoot(this.#reactRootElements.appRootElement));
    }).then(reactRoot => {
      if (!this.#getReactComponent) {} else {
        reactRoot.render(this.#getReactComponent(this.#reactRootElements));
      }
      return reactRoot;
    });
  }
  disconnectedCallback() {
    this.reactRootPromise = this.reactRootPromise.then(reactRoot => {
      if (!reactRoot) {
        throw new Error(`disconnectedCallback fired when reactRoot is already unmounted.`);
      }
      reactRoot.unmount();
      return null;
    });
  }
}
export const getReactWebComponent = ({
  webComponentName = versionedWebComponentName,
  getReactComponent,
  nonce
}) => {
  if (!customElements.get(webComponentName)) {
    customElements.define(webComponentName, WebComponentClass);
  }
  const element = document.createElement(webComponentName);
  element.setAttribute(webComponentDataAttributeName, "");
  element.setAttribute("nonce", nonce);
  element.setGetReactComponent(getReactComponent);
  return element;
};
export const renderReactInWebComponent = ({
  webComponentName,
  getReactComponent,
  webComponentChildren,
  webComponentParentElement,
  webComponentRootElement,
  nonce = window.cspNonce
}) => {
  const reactElement = getReactWebComponent({
    getReactComponent,
    webComponentName,
    nonce
  });
  if (webComponentChildren) {
    (Array.isArray(webComponentChildren) ? webComponentChildren : [webComponentChildren]).forEach(webComponentChild => {
      reactElement.appendChild(webComponentChild);
    });
  }
  if (webComponentParentElement) {
    webComponentParentElement.appendChild(reactElement);
  } else if (webComponentRootElement) {
    webComponentRootElement.appendChild(reactElement);
  }
  return reactElement;
};
//# sourceMappingURL=renderReactInWebComponent.js.map