/*
 * Copyright (C) 2019 Robert Bosch GmbH Copyright (C) 2019 Robert Bosch Manufacturing Solutions GmbH, Germany. All rights reserved.
 */

import { CollectionViewer, DataSource, SelectionModel } from '@angular/cdk/collections';
import { Component, OnInit } from '@angular/core';
import { PageEvent } from '@bci-web-core/web-components/dist/types/components/paginator/paginator.interface';
import { BehaviorSubject, fromEvent, Observable } from 'rxjs';
import { map, startWith } from 'rxjs/operators';

const ELEMENT_DATA: Element[] = [
  { position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H' },
  { position: 2, name: 'Helium', weight: null, symbol: 'He' },
  { position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li' },
  { position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be' },
  { position: 5, name: 'Boron', weight: 10.811, symbol: 'B' },
  { position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C' },
  { position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N' },
  { position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O' },
  { position: 9, name: 'Fluorine', weight: null, symbol: 'F' },
  { position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne' },
  { position: 11, name: 'Sodium', weight: 22.9897, symbol: 'Na' },
  { position: 12, name: 'Magnesium', weight: 24.305, symbol: 'Mg' },
  { position: 13, name: 'Aluminum', weight: 26.9815, symbol: 'Al' },
  { position: 14, name: 'Silicon', weight: 28.0855, symbol: 'Si' },
  { position: 15, name: 'Phosphorus', weight: 30.9738, symbol: 'P' },
  { position: 16, name: 'Sulfur', weight: 32.065, symbol: 'S' },
  { position: 17, name: 'Chlorine', weight: null, symbol: 'Cl' },
  { position: 18, name: 'Argon', weight: 39.948, symbol: 'Ar' },
  { position: 19, name: 'Potassium', weight: 39.0983, symbol: 'K' },
  { position: 20, name: 'Calcium', weight: 40.078, symbol: 'Ca' },
];

@Component({
  selector: 'bci-table-demo',
  templateUrl: 'table-demo.html',
  styleUrls: ['table-demo.scss'],
})
export class TableDemoComponent implements OnInit {
  displayedColumns = ['position', 'name', 'weight', 'symbol'];
  dataSource: PaginatorDataSource<Element>;
  selection: SelectionModel<Element> = new SelectionModel<Element>(false, [ELEMENT_DATA[3]]);
  pageSizeOptions = [5, 10, 20];
  enableStripesDirective = false;

  isMobile$: Observable<boolean>;
  checkScreenSize = (): boolean => document.body.offsetWidth < 768;

  ngOnInit() {
    // Simulate fetch data with a timeout
    // correlates with e2e tests for table demo, test waits 4 seconds for this simulated loading
    setTimeout(() => {
      this.loadDataSource(0, 10);
    }, 2000);

    const screenSizeChanged$ = fromEvent(window, 'resize').pipe(map(this.checkScreenSize));
    this.isMobile$ = screenSizeChanged$.pipe(startWith(this.checkScreenSize()));
  }

  onPageChange(pageEvent: PageEvent) {
    this.dataSource.pageIndex = pageEvent.pageIndex;
    this.dataSource.pageSize = pageEvent.pageSize;
  }

  toggleContent() {
    this.loadDataSource(0, this.dataSource.pageSize, this.dataSource.data.length > 0);
  }

  toggleStripesDirective() {
    if (this.enableStripesDirective) {
      this.enableStripesDirective = false;
    } else {
      this.enableStripesDirective = true;
    }
  }

  trackByName(index: number, item: Element) {
    if (item !== undefined) {
      return item.name;
    }
    return undefined;
  }

  private loadDataSource(index, pageSize, showNothing = false) {
    if (showNothing) {
      this.dataSource = new PaginatorDataSource<Element>();
      return;
    }
    this.dataSource = new PaginatorDataSource<Element>(ELEMENT_DATA);
  }
}

export interface Element {
  name: string;
  position: number;
  weight: number | null;
  symbol: string;
}

export class PaginatorDataSource<T> implements DataSource<T> {
  _allData: T[] = [];
  _paginated: T[] = [];
  pageData: {
    pageSize: number;
    pageIndex: number;
  } = {
    pageSize: 10,
    pageIndex: 0,
  };
  private readonly _renderData = new BehaviorSubject<T[]>([]);

  constructor(data?: T[]) {
    this.data = data || [];
  }

  get pageSize(): number {
    return this.pageData.pageSize;
  }

  set pageSize(pageSize: number) {
    this.pageData.pageSize = pageSize;
    this._filter();
  }

  get pageIndex(): number {
    return this.pageData.pageIndex;
  }

  set pageIndex(index: number) {
    this.pageData.pageIndex = index;
    this._filter();
  }

  get numberOfItems(): number {
    return this._allData.length;
  }

  get data(): T[] {
    return [...this._allData];
  }

  set data(data: T[]) {
    this._allData = data;
    this._filter();
  }

  get paginatedData(): T[] {
    return [...this._paginated];
  }

  /* eslint-disable-next-line @typescript-eslint/no-unused-vars */
  connect(collectionViewer: CollectionViewer): Observable<T[] | ReadonlyArray<T>> {
    return this._renderData;
  }

  _filter() {
    const startFromPage = this.pageData.pageIndex === 0 ? 0 : this.pageData.pageSize * this.pageData.pageIndex;
    const pageDataSize = startFromPage + this.pageData.pageSize;
    this._paginated = this._allData.slice(startFromPage, pageDataSize);
    this._renderData.next(this._paginated);
  }

  /* eslint-disable-next-line no-empty-function, @typescript-eslint/no-unused-vars */
  disconnect(collectionViewer: CollectionViewer): void {}
}
