import { Injectable, inject } from '@angular/core';
import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { EditableProfileAvatarSource, ProcessedProfileAvatar } from '../../domain/profile-avatar.models';
import { ProfileAvatarEditorComponent } from './profile-avatar-editor.component';

export const PROFILE_AVATAR_EDITOR_OVERLAY_CLASS = 'profile-avatar-editor-overlay-pane';

@Injectable({ providedIn: 'root' })
export class ProfileAvatarEditorService {
  private readonly overlay = inject(Overlay);
  private overlayRef: OverlayRef | null = null;

  open(source: EditableProfileAvatarSource): Promise<ProcessedProfileAvatar | null> {
    this.close();

    this.syncThemeVars();

    const overlayRef = this.overlay.create({
      disposeOnNavigation: true,
      panelClass: PROFILE_AVATAR_EDITOR_OVERLAY_CLASS,
      positionStrategy: this.overlay.position().global()
        .centerHorizontally()
        .centerVertically(),
      scrollStrategy: this.overlay.scrollStrategies.block()
    });

    this.overlayRef = overlayRef;

    const componentRef = overlayRef.attach(new ComponentPortal(ProfileAvatarEditorComponent));

    componentRef.setInput('source', source);

    return new Promise((resolve) => {
      let settled = false;

      const finish = (result: ProcessedProfileAvatar | null): void => {
        if (settled) {
          return;
        }

        settled = true;
        cancelSub.unsubscribe();
        confirmSub.unsubscribe();
        detachSub.unsubscribe();

        if (this.overlayRef === overlayRef) {
          this.overlayRef = null;
        }

        overlayRef.dispose();
        resolve(result);
      };
      const cancelSub = componentRef.instance.cancelled.subscribe(() => finish(null));
      const confirmSub = componentRef.instance.confirmed.subscribe((avatar) => finish(avatar));
      const detachSub = overlayRef.detachments().subscribe(() => finish(null));
    });
  }

  close(): void {
    if (!this.overlayRef) {
      return;
    }

    const overlayRef = this.overlayRef;

    this.overlayRef = null;
    overlayRef.dispose();
  }

  private syncThemeVars(): void {
    const appRoot = document.querySelector<HTMLElement>('[data-theme-key="appRoot"]');
    const container = document.querySelector<HTMLElement>('.cdk-overlay-container');

    if (!appRoot || !container) {
      return;
    }

    for (const prop of Array.from(appRoot.style)) {
      if (prop.startsWith('--')) {
        container.style.setProperty(prop, appRoot.style.getPropertyValue(prop));
      }
    }
  }
}
