import {
  animate,
  state,
  style,
  transition,
  trigger,
} from '@angular/animations';
import { CdkAccordionItem } from '@angular/cdk/accordion';
import { UniqueSelectionDispatcher } from '@angular/cdk/collections';
import {
  AfterContentInit,
  ChangeDetectionStrategy,
  ChangeDetectorRef,
  Component,
  ContentChild,
  Directive,
  Input,
  TemplateRef,
  ViewEncapsulation,
} from '@angular/core';
import { filter, startWith, take } from 'rxjs';

import { AccordionComponent } from '../accordion.component';

@Directive({
  selector: '[auiAccordionItemHeader]',
})
export class AccordionItemHeaderDirective {}
@Directive({
  selector: '[auiAccordionContent]',
})
export class AccordionItemContentDirective {}
@Component({
  selector: 'aui-accordion-item',
  templateUrl: 'accordion-item.component.html',
  styleUrls: ['accordion-item.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
  encapsulation: ViewEncapsulation.None,
  preserveWhitespaces: false,
  animations: [
    trigger('expand', [
      state('*', style({ height: 0 })),
      state('expanded', style({ height: '*' })),
      transition('* <=> expanded', [animate('0.1s ease-in-out')]),
    ]),
  ],
  viewProviders: [AccordionItemComponent],
})
export class AccordionItemComponent
  extends CdkAccordionItem
  implements AfterContentInit
{
  @Input()
  background = true;

  @ContentChild(AccordionItemContentDirective, {
    read: TemplateRef,
    static: true,
  })
  _lazyContentTpl: TemplateRef<unknown>;

  lazyContentTpl: TemplateRef<unknown>;

  // eslint-disable-next-line @typescript-eslint/no-useless-constructor
  constructor(
    accordion: AccordionComponent,
    cdr: ChangeDetectorRef,
    uniqueSelectionDispatcher: UniqueSelectionDispatcher,
  ) {
    super(accordion, cdr, uniqueSelectionDispatcher);
  }

  ngAfterContentInit() {
    if (this._lazyContentTpl) {
      // Render the content as soon as the accordion becomes open.
      this.opened
        .pipe(
          startWith(null as void),
          filter(() => !!this.expanded),
          take(1),
        )
        .subscribe(() => {
          this.lazyContentTpl = this._lazyContentTpl;
        });
    }
  }
}