//@ts-check

const createOptions = () => ({
  name: "my-custom-element",
  css: ":host{}",
  html: "",
  ParentClass: HTMLElement,
  observedAttributes: /** @type {string[]}*/ ([]),
});

/**
 * WIP: minimal API for custom elements. Do not use!
 * @typedef {ReturnType<typeof createOptions>} Options
 * @param {Partial<Options>} [options]
 */
export const createCustomElement = (options) => {
  const {
    name,
    css,
    html,
    observedAttributes: attrs,
    ParentClass,
  } = { ...createOptions(), ...options };

  class CustomClass extends ParentClass {
    static template = document.createElement("template");
    static stylesheet = new CSSStyleSheet();

    constructor(){
      super()
    }

    /**
     * Registers the custom element. If it was already registered, this is a no-op.
     * @param {string} tag
     */
    static define(tag = name) {
      if (!customElements.get(tag)) {
        customElements.define(tag, this);
      }
    }

    static get observedAttributes() {
      return attrs;
    }

    attributeChangedCallback(property, oldValue, newValue) {
      if (oldValue === newValue) {
        return;
      }
      this[property] = newValue;
    }

    /** @type {AbortController|null} */
    _abortController = null;

    /**
     * If no <template> tag is provided in the page, this uses the parent classe's
     * template and css to create markup
     * Use this in the constructor
     */
    _autoCreateShadow(){
      if (!this.shadowRoot) {
        const { stylesheet, template } =
          Object.getPrototypeOf(this).constructor;
        this.shadowRoot = this.attachShadow({ mode: "open" });
        this.shadowRoot.adoptedStyleSheets = [stylesheet];
        this.shadowRoot.replaceChildren(template.content.cloneNode(true));
      }
    }

    _getAbortSignal(){
      if(!this._abortController){
        this._abortController = new AbortController()
      }
      return this._abortController.signal
    }

    /**
     * Aborts any event that used the AbortSignal.
     * Use this in the `disconnectedCallback` call
     */
    _abort(){
      this._abortController && this._abortController.abort();
    }

  }

  const x = new CustomClass();
  

  CustomClass.template.innerHTML = html;
  CustomClass.stylesheet.replaceSync(css);
  Object.defineProperty(CustomClass, "name", { value: name.replace(/-/s,'') });
  return CustomClass;
};

export default createCustomElement