import { IDatasource, IGetRowsParams, IServerSideDatasource, IServerSideGetRowsParams, ColumnVO } from "ag-grid-community";
import { IRequestObject } from './repository';
import * as breeze from 'breeze-client';
import { AgGridToBreezeTransformer } from "./service-base";
import { GridOptions } from "./../resources/elements/utilities/ag-grid-helpers";

export interface IGetPredicatesFunc {
    (filterText: string): breeze.Predicate;
}

export interface IGetDataFunc {
    (requestObj: IRequestObject): Promise<{ results: any, fullCount?: number, error?: any }>;
}

export interface IGetGroupDataFunc {
    (valueCols: ColumnVO[], groupKeys: string[], requestObj: IRequestObject): Promise<{ results: any, fullCount?: number, error?: any }>;
}
export interface IBeforeFetchingFunc {
    (requestObj: IRequestObject): Promise<any>;
}

export interface IAgGridDataSource extends IDatasource {
    filterText: string;
    expands: string[];
    queryParameters: any;
    getRows(params: any);
    beforeFetching(requestObj: IRequestObject): IRequestObject;
}
export abstract class BaseGridDataSource implements IAgGridDataSource {
    predicates: breeze.Predicate;
    getPredicatesFunction: IGetPredicatesFunc;
    getDataFunction: IGetDataFunc;
    filterText: string;
    expands: string[];
    queryParameters: any;
    constructor(private resourceName: string) {
    }
    public getTransformer() {
        return new AgGridToBreezeTransformer(this.resourceName);
    }
    getRows(params: any) {
        throw new Error("Method not implemented.");
    }

    beforeFetching(requestObj: IRequestObject): IRequestObject {
        return requestObj;
    }

}

export class GridDataSource extends BaseGridDataSource {
    public getRows(params: IGetRowsParams) {
        let requestObj = this.getTransformer().getRequestObject(this, params);
        requestObj = this.beforeFetching(requestObj);
        var promise = this.getDataFunction(requestObj);
        promise
            .then((results) => {
                params.successCallback(results.results, results.fullCount);
            })
            .catch((reason) => params.failCallback());
        return promise;
    }
}

export class ServerSideDataSource extends BaseGridDataSource implements IServerSideDatasource {
    private gridOptions: GridOptions;
    private expandedGroupIds = [];
    public setGridOptions(gridOptions: GridOptions) {
        this.gridOptions = gridOptions;
        this.gridOptions.onRowGroupOpened = (params) => {
            var id = params.data.id;
            if (params.node.expanded) {
                this.expandedGroupIds.push(id);
            } else {
                this.expandedGroupIds = this.expandedGroupIds.filter(grpId => !grpId.startsWith(id));
            }
        }
    }
    public getGroupDataFunction: IGetGroupDataFunc = (requestObj) => {
        throw Error("Grouping cannot be handle in a generic way, you must provide a service class implementing getGroupDataFunction callback");
    }

    public async getRows(params: IServerSideGetRowsParams) {

        if (params.request.rowGroupCols.length > 0) {
            //let groupKey = params.request.groupKeys[0];
            let requestObj = this.getTransformer().getRequestObject(this, params.request);
            //requestObj.queryParameters = { groupKey };
            requestObj = this.beforeFetching(requestObj);

            let results = await this.getGroupDataFunction(params.request.valueCols, params.request.groupKeys, requestObj);
            params.success({ rowData: results.results, rowCount: results.fullCount });
            results.results.forEach(row => {
                if (this.expandedGroupIds.indexOf(row.id) > -1) {
                    var gridrow = this.gridOptions.api.getRowNode(row.id);
                    gridrow.setExpanded(true);
                }
            });
            //if (params.request.groupKeys.length === 0) {
            //    let requestObj = this.getTransformer().getRequestObject(this, params.request);
            //    let results = await this.getGroupDataFunction(requestObj);
            //    params.successCallback(results, results.length);
            //} else {
            //    let groupKey = params.request.groupKeys[0];
            //    let requestObj = this.getTransformer().getRequestObject(this, params.request);
            //    requestObj.queryParameters = { groupKey };
            //    requestObj = this.beforeFetching(requestObj);

            //    let results = await this.getDataFunction(requestObj);                
            //    params.successCallback(results.results, results.fullCount);
            //}
        }
        else {
            try {
                let requestObj = this.getTransformer().getRequestObject(this, params.request);
                requestObj = this.beforeFetching(requestObj);
                let results = await this.getDataFunction(requestObj);
                params.success({ rowData: results.results, rowCount: results.fullCount });
            }
            catch (reason) {
                params.fail();
            }
        }
    }
}



