import { Injectable, Inject, TemplateRef, Injector, Type, InjectionToken } from '@angular/core';
import { DOCUMENT } from '@angular/common';
import { Overlay, OverlayConfig, OverlayRef } from '@angular/cdk/overlay';
import { config } from './default-dialog.config';
import { ComponentPortal } from '@angular/cdk/portal';
import { ModalDialogueSharedComponent } from './component';
import { IsaModalOverlayRef } from './isa-modal-overlay-ref';
import { ModalContent } from './defs';
import { ModalDialogData } from './modal-dialog-data';

@Injectable({ providedIn: 'root' })
export class ModalService {
  modal: OverlayRef;

  constructor(@Inject(DOCUMENT) private document: Document, private overlay: Overlay, private injector: Injector) {}

  open<T>(content: ModalContent, data: ModalDialogData<T>): IsaModalOverlayRef<T> {
    if (this.modal) {
      this.modal.dispose();
    }

    const overlayRef = this.createOverlay();
    this.modal = overlayRef;
    const modalRef = new IsaModalOverlayRef<T>(overlayRef, content, data);

    const injector = this.createInjector(modalRef, { ...data, ref: modalRef });
    overlayRef.attach(new ComponentPortal(ModalDialogueSharedComponent, null, injector));

    return modalRef;
  }

  private createOverlay(): OverlayRef {
    return this.overlay.create(this.getOverlayConfig());
  }

  private getOverlayConfig(): OverlayConfig {
    return new OverlayConfig({ ...config });
  }

  private createInjector<T>(overlayRef: IsaModalOverlayRef, data: T) {
    return Injector.create({
      providers: [
        { provide: IsaModalOverlayRef, useValue: overlayRef },
        { provide: ModalDialogData, useValue: data },
      ],
      parent: this.injector,
    });
  }
}
