import * as plugins from './plugins.js';

export class DeesElement extends plugins.lit.LitElement {
  // INSTANCE
  @plugins.lit.property({ type: Boolean })
  public goBright: boolean = false;

  // domtools
  public domtoolsPromise: Promise<plugins.domtools.DomTools>;

  @plugins.lit.property()
  domtools?: plugins.domtools.DomTools;

  public rxSubscriptions: plugins.smartrx.rxjs.Subscription[] = [];
  private themeSubscription: plugins.smartrx.rxjs.Subscription;

  private elementDomReadyDeferred = plugins.domtools.plugins.smartpromise.defer();
  public elementDomReady = this.elementDomReadyDeferred.promise;

  constructor(optionsArg: plugins.domtools.IDomToolsContructorOptions = {}) {
    super();
    this.domtoolsPromise = plugins.domtools.elementBasic.setup(this, optionsArg);
    this.domtoolsPromise.then((domtoolsArg) => {
      this.domtools = domtoolsArg;
    });
  }

  public async connectedCallback() {
    super.connectedCallback();
    const domtools = await this.domtoolsPromise;
    this.themeSubscription = domtools.themeManager.themeObservable.subscribe((goBrightArg) => {
      this.goBright = goBrightArg;
    });
    this.rxSubscriptions.push(this.themeSubscription);
    for (const startupFunction of this.startupFunctions) {
      await startupFunction();
    }
    this.dispatchEvent(new CustomEvent('deesElementConnected'));
  }

  public firstUpdated(_changedProperties: Map<string | number | symbol, unknown>): void {
    super.firstUpdated(_changedProperties);
    this.elementDomReadyDeferred.resolve();
  }

  private startupFunctions: (() => void | Promise<any>)[] = [];
  public registerStartupFunction(startupFunctionArg: () => void) {
    this.startupFunctions.push(startupFunctionArg);
  }

  private garbageFunctions: (() => void | Promise<any>)[] = [];
  public registerGarbageFunction(garbageFunctionArg: () => void) {
    this.garbageFunctions.push(garbageFunctionArg);
  }

  public async disconnectedCallback() {
    await this.domtoolsPromise;
    super.disconnectedCallback();
    for (const subscription of this.rxSubscriptions) {
      subscription.unsubscribe();
    }
    for (const garbageFunction of this.garbageFunctions) {
      await garbageFunction();
    }
    this.dispatchEvent(new CustomEvent('deesElementDisconnected'));
  }
}