import { DataSource } from '@angular/cdk/collections'

import { MatPaginator } from '@angular/material/paginator'
import { MatSort } from '@angular/material/sort'

import { Observable, of as observableOf, merge, BehaviorSubject } from 'rxjs'
import { map } from 'rxjs/operators'

// import { gql } from 'apollo-angular'

import { ModelDataService } from '../_services/apollo.service'
import { AppInjector } from '../app-injector'

export class TableDataSource extends DataSource<object[]> {
    dataStream = new BehaviorSubject<object[]>([])
    set data(v: object[]) { this.dataStream.next(v); }
    get data(): object[] { return this.dataStream.value; }

    modelDef: object[]
    loading:boolean = true
    modelDataService: ModelDataService
    length: number = 0
    paginator: MatPaginator
    sort: MatSort
    displayedColumns: string[]

    constructor(
        paginator,
        sort,
        modelDef,
        displayedColumns
    ) {
        super()
        this.paginator = paginator
        this.sort = sort
        this.modelDef = modelDef
        this.displayedColumns = displayedColumns
        this.modelDataService = AppInjector.get(ModelDataService)
    }

    connect(): Observable<any> {
        let cols = this.displayedColumns.join(' ')
        console.warn('Migrate Graphql')
        let query = ''
        // let query = gql`query model {${this.modelDef['name']}{${cols}}}`
        return this.fetch(query)
    }

    disconnect(): void {
    }

    fetch(query): Observable<any> {
        this.modelDataService.get(query).pipe(map(
            data => {
                //let edges = data[this.modelDef['name']]['edges']
                //this.loading = data['loading']
                //this.data = edges.map(e => e.node)
                // Set the paginators length
                this.loading = false
                this.data = data[this.modelDef['name']]
                this.paginator.length = this.data.length
                return this.data
            }
        )).subscribe()

        const dataMutations = [
            this.dataStream,
            this.paginator.page,
            this.sort.sortChange
        ]

        return merge(...dataMutations).pipe(map(() => {
            return this.getPagedData(this.getSortedData([...this.data]))
        }))
    }

    private getPagedData(data: object[]) {
        const startIndex = this.paginator.pageIndex * this.paginator.pageSize
        return data.splice(startIndex, this.paginator.pageSize)
    }

    private getSortedData(data: object[]) {
        if (!this.sort.active || this.sort.direction === '') {
            return data
        }

        return data.sort((a, b) => {
            const isAsc = this.sort.direction === 'asc'
            let col = this.sort.active
            return compare(a[col], b[col], isAsc)
        })
    }

    set filter(searchString) {
        console.log(searchString)
    }
}

/** Simple sort comparator for example ID/Name columns (for client-side sorting). */
function compare(a, b, isAsc) {
  return (a < b ? -1 : 1) * (isAsc ? 1 : -1)
}
