import { provideAnimations } from '@angular/platform-browser/animations';
import { applicationConfig, Meta, StoryObj } from '@storybook/angular';
import { ToastServiceStoryComponent } from './toast-service.story-component';
import { ToastService } from './toast.service';

const code = `
import {
  Component,
  TemplateRef,
  ViewContainerRef,
  ChangeDetectionStrategy,
  ViewChild,
  ComponentRef, Output, EventEmitter
} from '@angular/core';
import {ToastComponent, ToastService} from '../../public-api';
import {take} from 'rxjs';

@Component({
  selector: 'nj-toast-ex',
  template: \`
    <nj-toast toastId="toast-1" [hasCloseIcon]="true" [shouldDismiss]="true" iconName="check" (closed)="closed.emit($event)"
              (dismissed)="dismissed.emit()">
      Toast Component ex Title
      <ng-container njToastBody>
        Toast body
      </ng-container>
    </nj-toast>
  \`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ToastExComponent {

  // Either use ViewChild to gain access to toast events
  @ViewChild(ToastComponent, {read: ToastComponent}) toast: ToastComponent;

  // Or Mirror toast events to be able to listen to them
  @Output() closed = new EventEmitter<Event>();

  @Output() dismissed = new EventEmitter<void>();

  constructor() {
  }
}

@Component({
  selector: 'app-toast-service-example',
  styles: [':host {display: flex; gap: 16px}'],
  template: \`
    <nj-button (buttonClick)="openToast(toastToOpen)">Open Toast</nj-button>
    <ng-template #toastToOpen>
      <nj-toast toastId="toast-2" [hasCloseIcon]="true" [shouldDismiss]="true" iconName="check"
                (closed)="onToastClose($event)" (dismissed)="onToastDismiss()">
        Toast Title
        <ng-container njToastBody>
          Toast body
        </ng-container>
      </nj-toast>
    </ng-template>

    <nj-button emphasis="subtle" (buttonClick)="openComponentToast()">Open Component toast</nj-button>

    <nj-button variant="secondary" (buttonClick)="toggleFullWidth()">Toggle Full Width</nj-button>
  \`,
  changeDetection: ChangeDetectionStrategy.OnPush
})
export class ToastServiceExampleComponent {
  isFullWidth = false;

  constructor(private viewContainerRef: ViewContainerRef, private toastService: ToastService) {
  }

  openToast(toast: TemplateRef<any>) {
    const toastRef = this.toastService.open(toast, {viewContainerRef: this.viewContainerRef});
  }

  openComponentToast() {
    const toastRef: ComponentRef<ToastExComponent> = this.toastService.open(ToastExComponent, {viewContainerRef: this.viewContainerRef});

    // If mirroring events in component
    toastRef.instance.closed
      .pipe(take(1))
      .subscribe(ev => {
        this.onToastClose(ev);
      });

    toastRef.instance.dismissed
      .pipe(take(1))
      .subscribe(() => {
        this.onToastDismiss();
      });

    // If using viewChild, we need to wrap in setTimeout to make sure Custom component is already rendered,
    // and we have access to child ToastComponent
    setTimeout(() => {
      const toastComponent = toastRef.instance.toast;
      if (toastComponent) {
        toastComponent.closed
          .pipe(take(1))
          .subscribe(ev => {
            this.onToastClose(ev);
          });

        toastComponent.dismissed
          .pipe(take(1))
          .subscribe(() => {
            this.onToastDismiss();
          });
      }
    });
  }

  onToastClose(event: Event) {
    console.warn('Do Action on toast close');
  }

  onToastDismiss() {
    console.warn('Do Action on toast dismiss');
  }

  toggleFullWidth() {
    this.isFullWidth = !this.isFullWidth;
    this.toastService.setConfig({isContainerFullWidth: this.isFullWidth});
  }
}
`;

const meta: Meta<ToastServiceStoryComponent> = {
  title: 'Components/Toast/Toast Service',
  id: 'toast-service',
  component: ToastServiceStoryComponent,
  decorators: [
    applicationConfig({
      providers: [provideAnimations(), ToastService]
    })
  ],
  parameters: {
    docs: {
      description: {
        component: 'Toast component comes with a service that allows opening a Toast from a TemplateRef or a Component'
      },
      source: {
        language: 'typescript',
        type: 'auto',
        code
      }
    }
  },
  argTypes: {
    isInverse: {
      control: {
        type: null
      }
    },
    closed: {
      control: {
        type: null
      }
    },
    dismissed: {
      control: {
        type: null
      }
    }
  }
};

export default meta;

type Story = StoryObj<ToastServiceStoryComponent>;

export const toastService: Story = {
  args: {
    toastId: 'toast-2',
    iconName: 'check'
  }
};
