import { GlobalPositionStrategy, Overlay } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { Injectable, Injector, StaticProvider, TemplateRef, Type } from '@angular/core';
import { UiModalConfig } from './defs/modal-config';
import { UiModalRef } from './defs/modal-ref';
import { UiErrorModalComponent } from './error-modal';
import { UiModalComponent } from './modal.component';

@Injectable({ providedIn: 'root' })
export class UiModalService {
  constructor(
    private overlay: Overlay,
    private injector: Injector,
  ) {}

  open<R = any, T = any>({
    content,
    title,
    data,
    config,
    providers,
  }: {
    content: TemplateRef<any> | Type<any>;
    title?: string;
    data?: T;
    config?: UiModalConfig;
    providers?: StaticProvider[];
  }): UiModalRef<R> {
    const configs = new UiModalConfig({
      positionStrategy: new GlobalPositionStrategy().centerHorizontally().centerVertically(),
      hasBackdrop: true,
      backdropClose: true,
      width: '917px',
      panelClass: ['modal-overflow'],
      showScrollbarX: false,
      showScrollbarY: true,
      canClose: true,
      padding: true,
      ...config,
    });

    const overlay = this.overlay.create(configs);

    const modalRef = new UiModalRef<R, T>(overlay, content, title, configs, data);

    const injector = this.createInjector(modalRef, providers);
    overlay.attach(new ComponentPortal(UiModalComponent, null, injector));

    if (configs.backdropClose) {
      overlay.backdropClick().subscribe(() => modalRef._close({ type: 'backdropClick', data: null }));
    }

    return modalRef;
  }

  createInjector(ref: UiModalRef, additionalProviders: StaticProvider[] = []): Injector {
    return Injector.create({
      providers: [{ provide: UiModalRef, useValue: ref }, ...additionalProviders],
      parent: this.injector,
    });
  }

  error(title: string, error: Error): UiModalRef<undefined> {
    return this.open({
      content: UiErrorModalComponent,
      title,
      data: error,
    });
  }
}
