import { autoinject, bindable, customAttribute } from 'aurelia-framework';

@autoinject()
@customAttribute('ui-infinite-scroll')
export class UIInfiniteScrollCustomAttribute {
  public static ScrollEventName: string = 'scroll';

  private isTicking: boolean = false;

  @bindable callback: Function;
  @bindable scrollBuffer: number = 0;
  @bindable isActive: boolean = true;
  @bindable loadOnBottom: boolean = true;

  constructor(private element: Element) {
    this.element = element;
  }

  public attached() {
    this.element.addEventListener(UIInfiniteScrollCustomAttribute.ScrollEventName, this.onScrollChange);
    this.onScrollChange();
  }

  public detached() {
    this.element.removeEventListener(UIInfiniteScrollCustomAttribute.ScrollEventName, this.onScrollChange);
  }

  private callbackChanged(newCallback: Function) {
    this.callback = newCallback;
  }

  private scrollBufferChanged(buffer: number) {
    this.scrollBuffer = +buffer;
  }

  private onScrollChange = () => {
    if (!this.isActive) {
      return false;
    }

    if (!this.isTicking) {
      window.requestAnimationFrame(() => {
        this.checkScrollPosition();
        this.isTicking = false;
      });
    }

    this.isTicking = true;
  }

  private checkScrollPosition() {
    if (this.callback) {
      const windowScrollPosition = this.element.offsetHeight + this.element.scrollTop;
      const isPageScrolledToElementBottom = (windowScrollPosition + this.scrollBuffer) >= (this.element.scrollHeight - 10);
      const isElementScrolledtoTop = this.element.scrollTop == 0;

      if (this.loadOnBottom === true && isPageScrolledToElementBottom) {
        this.callback();
      }
      if (this.loadOnBottom === false && isElementScrolledtoTop) {
        this.callback();
      }
    }
  }
}
