import { Component, OnInit, ChangeDetectionStrategy, ChangeDetectorRef, OnDestroy, ViewChild, ViewRef } from '@angular/core';

import { GoodsInSearch } from 'apps/sales/src/app/core/models/GoodsInSearch.model';
import { GoodsInSearchResultsDataSource } from './goods-in-search-results.datasource';
import { Subject } from 'rxjs';
import { GoodsInService } from 'apps/sales/src/app/core/services/goods-in.service';
import { Store } from '@ngxs/store';
import { AppState } from 'apps/sales/src/app/core/store/state/app.state';
import { takeUntil, filter, switchMap, tap } from 'rxjs/operators';
import { ModuleSwitcher } from 'apps/sales/src/app/core/models/app-switcher.enum';
import { GoodsInSelectors } from 'apps/sales/src/app/core/store/selectors/goods-in.selectors';
import { isNullOrUndefined } from 'util';
import { OrderItemListItemDTO } from '@swagger/oms';
import { SetGoodsInUseCache } from 'apps/sales/src/app/core/store/actions/goods-in.actions';
import { GOODS_IN_SCROLL_INDEX } from 'apps/sales/src/app/core/utils/app.constants';
import { ListRange } from '@angular/cdk/collections';
import { CdkVirtualScrollViewport } from '@angular/cdk/scrolling';

@Component({
  selector: 'app-goods-in-search-results',
  templateUrl: './goods-in-search-results.component.html',
  styleUrls: ['./goods-in-search-results.component.scss'],
  changeDetection: ChangeDetectionStrategy.OnPush,
})
export class GoodsInSearchResultsComponent implements OnInit, OnDestroy {
  @ViewChild('scroller', { static: true }) scroller: CdkVirtualScrollViewport;
  goodsInSearch: GoodsInSearch;
  ds: GoodsInSearchResultsDataSource;
  destroy$ = new Subject();
  loading = true;
  useCache = false;
  id: number;
  doScroll = true;
  constructor(private cdr: ChangeDetectorRef, private goodsInService: GoodsInService, private store: Store) {}

  ngOnInit() {
    this.initialize();
  }

  ngOnDestroy() {
    this.destroy$.next();
  }

  initialize() {
    this.store
      .select(AppState.activeModule)
      .pipe(
        takeUntil(this.destroy$),
        filter((activeModule) => activeModule && activeModule === ModuleSwitcher.Branch),
        switchMap(() => {
          return this.store.select(GoodsInSelectors.getGoodsInCurrentSearch);
        }),
        filter((data) => !isNullOrUndefined(data))
      )
      .subscribe((search) => {
        this.useCache = this.store.selectSnapshot(GoodsInSelectors.getGoodsInCacheState);
        this.goodsInSearch = search;
        this.id = this.store.selectSnapshot(AppState.getCurrentProcessId);
        this.loadDataSource(search);
        this.useCache.ifTrue(() => this.store.dispatch(new SetGoodsInUseCache(false)));
      });

    this.scroller.renderedRangeStream
      .pipe(
        takeUntil(this.destroy$),
        filter((data) => !isNullOrUndefined(data))
      )
      .subscribe((range) => {
        if (this.doScroll) {
          this.scrollToIndexCached(range);
        }
      });
  }

  loadDataSource(goodsInSearch: GoodsInSearch) {
    this.ds = new GoodsInSearchResultsDataSource(goodsInSearch, this.store, this.goodsInService, this.useCache);
    this.loading = false;
    this.detectChanges();
  }

  isChildItem(curr: OrderItemListItemDTO, index: number) {
    if (!curr || index < 1 || !this.ds) {
      return false;
    }
    const prev = this.ds.getPrevItem(index);
    if (!prev) {
      return false;
    }
    return curr.firstName === prev.firstName && curr.lastName === prev.lastName;
  }

  hasTrailingItem(curr: OrderItemListItemDTO, index: number) {
    if (!curr || !this.ds) {
      return false;
    }
    const next = this.ds.getNextItem(index);
    if (!next) {
      return false;
    }
    return curr.firstName === next.firstName && curr.lastName === next.lastName;
  }

  scrollToIndexCached(range: ListRange) {
    setTimeout(() => {
      const index = this.getIndex();
      this.scroller.scrollToIndex(index);
      if (range.start <= index && range.end >= index) {
        this.doScroll = false;
        sessionStorage.removeItem(GOODS_IN_SCROLL_INDEX);
      }
    }, 1);
  }

  getIndex() {
    const index = sessionStorage.getItem(GOODS_IN_SCROLL_INDEX);
    if (!isNullOrUndefined(index)) {
      const ids = index.split(':');
      if (this.id === +ids[1]) {
        return +ids[0];
      }
    }
    return 0;
  }

  detectChanges() {
    setTimeout(() => {
      if (this.cdr !== null && this.cdr !== undefined && !(this.cdr as ViewRef).destroyed) {
        this.cdr.detectChanges();
      }
    }, 0);
  }
}
