import { NumberInput, coerceElement, coerceNumberProperty } from '@angular/cdk/coercion';
import { Directive, ElementRef, EventEmitter, HostListener, Input, Output, inject } from '@angular/core';

@Directive({ selector: '[sharedScrollContainer]', standalone: true, host: { class: 'shared-scroll-container' } })
export class ScrollContainerDirective {
  elementRef = inject(ElementRef);

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

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

  private _delta: number = 50;

  @Input()
  set delta(value: NumberInput) {
    this._delta = coerceNumberProperty(value);
  }

  get scrollPosition() {
    const element: HTMLElement = coerceElement(this.elementRef);
    return element.scrollTop;
  }

  @HostListener('scroll', ['$event'])
  onScroll(_: Event) {
    const element: HTMLElement = coerceElement(this.elementRef);
    const { scrollTop, scrollHeight, clientHeight } = element;

    if (scrollTop === 0) {
      this.scrolledToTop.emit();
    } else if (scrollTop + clientHeight + this._delta >= scrollHeight) {
      this.scrolledToBottom.emit();
    }
  }

  scrollToIndex(index: number) {
    const element: HTMLElement = coerceElement(this.elementRef);
    const { scrollHeight, clientHeight } = element;
    const itemHeight = scrollHeight / clientHeight;
    const scrollPosition = index * itemHeight;
    element.scrollTo({ top: scrollPosition });
  }

  scrollTo(position: number) {
    const element: HTMLElement = coerceElement(this.elementRef);
    element.scrollTo({ top: position });
  }

  scrollToTop() {
    const element: HTMLElement = coerceElement(this.elementRef);
    element.scrollTo({ top: 0 });
  }

  scrollToBottom() {
    const element: HTMLElement = coerceElement(this.elementRef);
    element.scrollTo({ top: element.scrollHeight });
  }
}
